direct-io.hg
changeset 5514:aa52b853c28b
bitkeeper revision 1.1718.1.7 (42b742f8NxTuN2pqCHFAWI78dbEYKw)
Initial MAC (sHype) support from IBM.
Defaults to NULL policy for now.
Signed-off-by: Reiner Sailer <sailer@us.ibm.com>
Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
Signed-off-by: Steven Hand <steven@xensource.com>
Initial MAC (sHype) support from IBM.
Defaults to NULL policy for now.
Signed-off-by: Reiner Sailer <sailer@us.ibm.com>
Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
Signed-off-by: Steven Hand <steven@xensource.com>
line diff
1.1 --- a/.rootkeys Sun Jun 19 17:05:55 2005 +0000 1.2 +++ b/.rootkeys Mon Jun 20 22:28:08 2005 +0000 1.3 @@ -785,6 +785,8 @@ 40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/mis 1.4 41adc641dV-0cDLSyzMs5BT8nL7v3Q tools/misc/xenperf.c 1.5 4056f5155QYZdsk-1fLdjsZPFTnlhg tools/misc/xensymoops 1.6 40cf2937dqM1jWW87O5OoOYND8leuA tools/misc/xm 1.7 +42b742f6JFcp6LFpYu-B4AEsfQwSFw tools/policy/Makefile 1.8 +42b742f66XOdRMrwaHvbCdSSQyCrFw tools/policy/policy_tool.c 1.9 4270cc81g3nSNYCZ1ryCMDEbLtMtbQ tools/pygrub/Makefile 1.10 4270deeccyRsJn6jLnRh9odRtMW9SA tools/pygrub/README 1.11 4270cc81EIl7NyaS3Av6IPRk2c2a6Q tools/pygrub/setup.py 1.12 @@ -1101,6 +1103,12 @@ 4050c413NtuyIq5lsYJV4P7KIjujXw tools/xen 1.13 3f72f1bdJPsV3JCnBqs9ddL9tr6D2g xen/COPYING 1.14 3ddb79bcbOVHh38VJzc97-JEGD4dJQ xen/Makefile 1.15 3ddb79bcWnTwYsQRWl_PaneJfa6p0w xen/Rules.mk 1.16 +42b742f6XHTfIEm_hUPtzjKr37LVhw xen/acm/Makefile 1.17 +42b742f6tHzn0fZWH3TjPva8gbqpow xen/acm/acm_chinesewall_hooks.c 1.18 +42b742f6bM8kZwuIUbepHZ8SQQkjJA xen/acm/acm_core.c 1.19 +42b742f6cwfrPubqH47gQpke8xkYSA xen/acm/acm_null_hooks.c 1.20 +42b742f69qSxm5MM-wtPaWtCqyI3KA xen/acm/acm_policy.c 1.21 +42b742f6VbmdlwekQRMhXugjcu9QXg xen/acm/acm_simple_type_enforcement_hooks.c 1.22 421098b25A0RvuYN3rP28ga3_FN3_Q xen/arch/ia64/Makefile 1.23 421098b2okIeYXS9w9avmSozls61xA xen/arch/ia64/Rules.mk 1.24 421098b21p12UcKjHBrLh_LjlvNEwA xen/arch/ia64/acpi.c 1.25 @@ -1324,6 +1332,7 @@ 3ddb79bduhSEZI8xa7IbGQCpap5y2A xen/commo 1.26 41a61536SZbR6cj1ukWTb0DYU-vz9w xen/common/multicall.c 1.27 3ddb79bdD4SLmmdMD7yLW5HcUWucXw xen/common/page_alloc.c 1.28 3e54c38dkHAev597bPr71-hGzTdocg xen/common/perfc.c 1.29 +42b742f6mgq9puEr7lUrLST0VEpsig xen/common/policy_ops.c 1.30 40589968dD2D1aejwSOvrROg7fOvGQ xen/common/sched_bvt.c 1.31 41ebbfe9oF1BF3cH5v7yE3eOL9uPbA xen/common/sched_sedf.c 1.32 3e397e6619PgAfBbw2XFbXkewvUWgw xen/common/schedule.c 1.33 @@ -1339,6 +1348,9 @@ 3e4a8cb7alzQCDKS7MlioPoHBKYkdQ xen/drive 1.34 4049e6bfNSIq7s7OV-Bd69QD0RpR2Q xen/drivers/char/console.c 1.35 4298e018XQtZkCdufpyFimOGZqqsFA xen/drivers/char/ns16550.c 1.36 3e4a8cb7nMChlro4wvOBo76n__iCFA xen/drivers/char/serial.c 1.37 +42b742f6OteAMPWnoqxqfRX3yxD0yw xen/include/acm/acm_core.h 1.38 +42b742f6XfIijctEwA0YWL2BoWtDNg xen/include/acm/acm_endian.h 1.39 +42b742f6jXvp1vdbU2v2WJjTPku65A xen/include/acm/acm_hooks.h 1.40 40715b2cFpte_UNWnBZW0Du7z9AhTQ xen/include/acpi/acconfig.h 1.41 40715b2ctNvVZ058w8eM8DR9hOat_A xen/include/acpi/acexcep.h 1.42 40715b2com8I01qcHcAw47e93XsCqQ xen/include/acpi/acglobal.h 1.43 @@ -1489,6 +1501,8 @@ 404f1bb86rAXB3aLS1vYdcqpJiEcyg xen/inclu 1.44 404f1bc4tWkB9Qr8RkKtZGW5eMQzhw xen/include/asm-x86/x86_64/uaccess.h 1.45 422f27c8RHFkePhD34VIEpMMqofZcA xen/include/asm-x86/x86_emulate.h 1.46 400304fcmRQmDdFYEzDh0wcBba9alg xen/include/public/COPYING 1.47 +42b742f6duiOTlZvysQkRYZHYBXqvg xen/include/public/acm.h 1.48 +42b742f7TIMsQgUaNDJXp3QlBve2SQ xen/include/public/acm_dom0_setup.h 1.49 421098b7OKb9YH_EUA_UpCxBjaqtgA xen/include/public/arch-ia64.h 1.50 404f1bc68SXxmv0zQpXBWGrCzSyp8w xen/include/public/arch-x86_32.h 1.51 404f1bc7IwU-qnH8mJeVu0YsNGMrcw xen/include/public/arch-x86_64.h 1.52 @@ -1502,6 +1516,7 @@ 40f5623cTZ80EwjWUBlh44A9F9i_Lg xen/inclu 1.53 41d40e9b8zCk5VDqhVbuQyhc7G3lqA xen/include/public/io/ring.h 1.54 41ee5e8c6mLxIx82KPsbpt_uts_vSA xen/include/public/io/usbif.h 1.55 4051db79512nOCGweabrFWO2M2h5ng xen/include/public/physdev.h 1.56 +42b742f7Lzy8SKKG25L_-fgk5FHA2Q xen/include/public/policy_ops.h 1.57 40589968wmhPmV5-ENbBYmMjnedgKw xen/include/public/sched_ctl.h 1.58 404f3d2eR2Owk-ZcGOx9ULGHg3nrww xen/include/public/trace.h 1.59 42b5a5f2QC1IxeuwCwwsOEhvcJ2BJg xen/include/public/version.h
2.1 --- a/tools/Makefile Sun Jun 19 17:05:55 2005 +0000 2.2 +++ b/tools/Makefile Mon Jun 20 22:28:08 2005 +0000 2.3 @@ -12,6 +12,7 @@ SUBDIRS += xcs 2.4 SUBDIRS += xcutils 2.5 SUBDIRS += pygrub 2.6 SUBDIRS += firmware 2.7 +SUBDIRS += policy 2.8 2.9 .PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean 2.10
3.1 --- a/tools/libxc/xc.h Sun Jun 19 17:05:55 2005 +0000 3.2 +++ b/tools/libxc/xc.h Mon Jun 20 22:28:08 2005 +0000 3.3 @@ -110,6 +110,7 @@ int xc_waitdomain_core(int domain, 3.4 3.5 typedef struct { 3.6 u32 domid; 3.7 + u32 ssidref; 3.8 unsigned int dying:1, crashed:1, shutdown:1, 3.9 paused:1, blocked:1, running:1; 3.10 unsigned int shutdown_reason; /* only meaningful if shutdown==1 */ 3.11 @@ -124,6 +125,7 @@ typedef struct { 3.12 3.13 typedef dom0_getdomaininfo_t xc_domaininfo_t; 3.14 int xc_domain_create(int xc_handle, 3.15 + u32 ssidref, 3.16 u32 *pdomid); 3.17 3.18
4.1 --- a/tools/libxc/xc_domain.c Sun Jun 19 17:05:55 2005 +0000 4.2 +++ b/tools/libxc/xc_domain.c Mon Jun 20 22:28:08 2005 +0000 4.3 @@ -9,6 +9,7 @@ 4.4 #include "xc_private.h" 4.5 4.6 int xc_domain_create(int xc_handle, 4.7 + u32 ssidref, 4.8 u32 *pdomid) 4.9 { 4.10 int err; 4.11 @@ -16,6 +17,7 @@ int xc_domain_create(int xc_handle, 4.12 4.13 op.cmd = DOM0_CREATEDOMAIN; 4.14 op.u.createdomain.domain = (domid_t)*pdomid; 4.15 + op.u.createdomain.ssidref = ssidref; 4.16 if ( (err = do_dom0_op(xc_handle, &op)) != 0 ) 4.17 return err; 4.18 4.19 @@ -101,6 +103,7 @@ int xc_domain_getinfo(int xc_handle, 4.20 info->crashed = 1; 4.21 } 4.22 4.23 + info->ssidref = op.u.getdomaininfo.ssidref; 4.24 info->nr_pages = op.u.getdomaininfo.tot_pages; 4.25 info->max_memkb = op.u.getdomaininfo.max_pages<<(PAGE_SHIFT); 4.26 info->shared_info_frame = op.u.getdomaininfo.shared_info_frame;
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/tools/policy/Makefile Mon Jun 20 22:28:08 2005 +0000 5.3 @@ -0,0 +1,36 @@ 5.4 +XEN_ROOT = ../.. 5.5 +include $(XEN_ROOT)/tools/Rules.mk 5.6 + 5.7 +SRCS = policy_tool.c 5.8 +CFLAGS += -static 5.9 +CFLAGS += -Wall 5.10 +CFLAGS += -Werror 5.11 +CFLAGS += -O3 5.12 +CFLAGS += -fno-strict-aliasing 5.13 +CFLAGS += -I. 5.14 + 5.15 +all: build 5.16 +build: mk-symlinks 5.17 + $(MAKE) policy_tool 5.18 + 5.19 +default: all 5.20 + 5.21 +install: all 5.22 + 5.23 +policy_tool : policy_tool.c 5.24 + $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< 5.25 + 5.26 +clean: 5.27 + rm -rf policy_tool xen 5.28 + 5.29 + 5.30 +LINUX_ROOT := $(wildcard $(XEN_ROOT)/linux-2.6.*-xen-sparse) 5.31 +mk-symlinks: 5.32 + [ -e xen/linux ] || mkdir -p xen/linux 5.33 + [ -e xen/io ] || mkdir -p xen/io 5.34 + ( cd xen >/dev/null ; \ 5.35 + ln -sf ../$(XEN_ROOT)/xen/include/public/*.h . ) 5.36 + ( cd xen/io >/dev/null ; \ 5.37 + ln -sf ../../$(XEN_ROOT)/xen/include/public/io/*.h . ) 5.38 + ( cd xen/linux >/dev/null ; \ 5.39 + ln -sf ../../$(LINUX_ROOT)/include/asm-xen/linux-public/*.h . )
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/tools/policy/policy_tool.c Mon Jun 20 22:28:08 2005 +0000 6.3 @@ -0,0 +1,557 @@ 6.4 +/**************************************************************** 6.5 + * policy_tool.c 6.6 + * 6.7 + * Copyright (C) 2005 IBM Corporation 6.8 + * 6.9 + * Authors: 6.10 + * Reiner Sailer <sailer@watson.ibm.com> 6.11 + * Stefan Berger <stefanb@watson.ibm.com> 6.12 + * 6.13 + * This program is free software; you can redistribute it and/or 6.14 + * modify it under the terms of the GNU General Public License as 6.15 + * published by the Free Software Foundation, version 2 of the 6.16 + * License. 6.17 + * 6.18 + * sHype policy management tool. This code runs in a domain and 6.19 + * manages the Xen security policy by interacting with the 6.20 + * Xen access control module via a /proc/xen/policycmd proc-ioctl, 6.21 + * which is translated into a policy_op hypercall into Xen. 6.22 + * 6.23 + * todo: implement setpolicy to dynamically set a policy cache. 6.24 + */ 6.25 +#include <unistd.h> 6.26 +#include <stdio.h> 6.27 +#include <errno.h> 6.28 +#include <fcntl.h> 6.29 +#include <sys/mman.h> 6.30 +#include <sys/types.h> 6.31 +#include <sys/stat.h> 6.32 +#include <stdlib.h> 6.33 +#include <sys/ioctl.h> 6.34 +#include <string.h> 6.35 +#include <stdint.h> 6.36 +#include <netinet/in.h> 6.37 + 6.38 +typedef uint8_t u8; 6.39 +typedef uint16_t u16; 6.40 +typedef uint32_t u32; 6.41 +typedef uint64_t u64; 6.42 +typedef int8_t s8; 6.43 +typedef int16_t s16; 6.44 +typedef int32_t s32; 6.45 +typedef int64_t s64; 6.46 + 6.47 +#include <xen/acm.h> 6.48 + 6.49 +#include <xen/policy_ops.h> 6.50 + 6.51 +#include <xen/linux/privcmd.h> 6.52 + 6.53 +#define ERROR(_m, _a...) \ 6.54 + fprintf(stderr, "ERROR: " _m "\n" , ## _a ) 6.55 + 6.56 +#define PERROR(_m, _a...) \ 6.57 + fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \ 6.58 + errno, strerror(errno)) 6.59 + 6.60 +static inline int do_policycmd(int xc_handle, 6.61 + unsigned int cmd, 6.62 + unsigned long data) 6.63 +{ 6.64 + return ioctl(xc_handle, cmd, data); 6.65 +} 6.66 + 6.67 +static inline int do_xen_hypercall(int xc_handle, 6.68 + privcmd_hypercall_t *hypercall) 6.69 +{ 6.70 + return do_policycmd(xc_handle, 6.71 + IOCTL_PRIVCMD_HYPERCALL, 6.72 + (unsigned long)hypercall); 6.73 +} 6.74 + 6.75 +static inline int do_policy_op(int xc_handle, policy_op_t *op) 6.76 +{ 6.77 + int ret = -1; 6.78 + privcmd_hypercall_t hypercall; 6.79 + 6.80 + op->interface_version = POLICY_INTERFACE_VERSION; 6.81 + 6.82 + hypercall.op = __HYPERVISOR_policy_op; 6.83 + hypercall.arg[0] = (unsigned long)op; 6.84 + 6.85 + if ( mlock(op, sizeof(*op)) != 0 ) 6.86 + { 6.87 + PERROR("Could not lock memory for Xen policy hypercall"); 6.88 + goto out1; 6.89 + } 6.90 + 6.91 + if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 ) 6.92 + { 6.93 + if ( errno == EACCES ) 6.94 + fprintf(stderr, "POLICY operation failed -- need to" 6.95 + " rebuild the user-space tool set?\n"); 6.96 + goto out2; 6.97 + } 6.98 + 6.99 + out2: (void)munlock(op, sizeof(*op)); 6.100 + out1: return ret; 6.101 +} 6.102 + 6.103 +/*************************** DUMPS *******************************/ 6.104 + 6.105 +void acm_dump_chinesewall_buffer(void *buf, int buflen) { 6.106 + 6.107 + struct acm_chwall_policy_buffer *cwbuf = (struct acm_chwall_policy_buffer *)buf; 6.108 + domaintype_t *ssids, *conflicts, *running_types, *conflict_aggregate; 6.109 + int i,j; 6.110 + 6.111 + 6.112 + if (htons(cwbuf->policy_code) != ACM_CHINESE_WALL_POLICY) { 6.113 + printf("CHINESE WALL POLICY CODE not found ERROR!!\n"); 6.114 + return; 6.115 + } 6.116 + printf("\n\nChinese Wall policy:\n"); 6.117 + printf("====================\n"); 6.118 + printf("Max Types = %x.\n", ntohs(cwbuf->chwall_max_types)); 6.119 + printf("Max Ssidrefs = %x.\n", ntohs(cwbuf->chwall_max_ssidrefs)); 6.120 + printf("Max ConfSets = %x.\n", ntohs(cwbuf->chwall_max_conflictsets)); 6.121 + printf("Ssidrefs Off = %x.\n", ntohs(cwbuf->chwall_ssid_offset)); 6.122 + printf("Conflicts Off = %x.\n", ntohs(cwbuf->chwall_conflict_sets_offset)); 6.123 + printf("Runing T. Off = %x.\n", ntohs(cwbuf->chwall_running_types_offset)); 6.124 + printf("C. Agg. Off = %x.\n", ntohs(cwbuf->chwall_conflict_aggregate_offset)); 6.125 + printf("\nSSID To CHWALL-Type matrix:\n"); 6.126 + 6.127 + ssids = (domaintype_t *)(buf + ntohs(cwbuf->chwall_ssid_offset)); 6.128 + for(i=0; i< ntohs(cwbuf->chwall_max_ssidrefs); i++) { 6.129 + printf("\n ssidref%2x: ", i); 6.130 + for(j=0; j< ntohs(cwbuf->chwall_max_types); j++) 6.131 + printf("%02x ", ntohs(ssids[i*ntohs(cwbuf->chwall_max_types) + j])); 6.132 + } 6.133 + printf("\n\nConfict Sets:\n"); 6.134 + conflicts = (domaintype_t *)(buf + ntohs(cwbuf->chwall_conflict_sets_offset)); 6.135 + for(i=0; i< ntohs(cwbuf->chwall_max_conflictsets); i++) { 6.136 + printf("\n c-set%2x: ", i); 6.137 + for(j=0; j< ntohs(cwbuf->chwall_max_types); j++) 6.138 + printf("%02x ", ntohs(conflicts[i*ntohs(cwbuf->chwall_max_types) +j])); 6.139 + } 6.140 + printf("\n"); 6.141 + 6.142 + printf("\nRunning\nTypes: "); 6.143 + if (ntohs(cwbuf->chwall_running_types_offset)) { 6.144 + running_types = (domaintype_t *)(buf + ntohs(cwbuf->chwall_running_types_offset)); 6.145 + for(i=0; i< ntohs(cwbuf->chwall_max_types); i++) { 6.146 + printf("%02x ", ntohs(running_types[i])); 6.147 + } 6.148 + printf("\n"); 6.149 + } else { 6.150 + printf("Not Reported!\n"); 6.151 + } 6.152 + printf("\nConflict\nAggregate Set: "); 6.153 + if (ntohs(cwbuf->chwall_conflict_aggregate_offset)) { 6.154 + conflict_aggregate = (domaintype_t *)(buf + ntohs(cwbuf->chwall_conflict_aggregate_offset)); 6.155 + for(i=0; i< ntohs(cwbuf->chwall_max_types); i++) { 6.156 + printf("%02x ", ntohs(conflict_aggregate[i])); 6.157 + } 6.158 + printf("\n\n"); 6.159 + } else { 6.160 + printf("Not Reported!\n"); 6.161 + } 6.162 +} 6.163 + 6.164 +void acm_dump_ste_buffer(void *buf, int buflen) { 6.165 + 6.166 + struct acm_ste_policy_buffer *stebuf = (struct acm_ste_policy_buffer *)buf; 6.167 + domaintype_t *ssids; 6.168 + int i,j; 6.169 + 6.170 + 6.171 + if (ntohs(stebuf->policy_code) != ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) { 6.172 + printf("SIMPLE TYPE ENFORCEMENT POLICY CODE not found ERROR!!\n"); 6.173 + return; 6.174 + } 6.175 + printf("\nSimple Type Enforcement policy:\n"); 6.176 + printf("===============================\n"); 6.177 + printf("Max Types = %x.\n", ntohs(stebuf->ste_max_types)); 6.178 + printf("Max Ssidrefs = %x.\n", ntohs(stebuf->ste_max_ssidrefs)); 6.179 + printf("Ssidrefs Off = %x.\n", ntohs(stebuf->ste_ssid_offset)); 6.180 + printf("\nSSID To STE-Type matrix:\n"); 6.181 + 6.182 + ssids = (domaintype_t *)(buf + ntohs(stebuf->ste_ssid_offset)); 6.183 + for(i=0; i< ntohs(stebuf->ste_max_ssidrefs); i++) { 6.184 + printf("\n ssidref%2x: ", i); 6.185 + for(j=0; j< ntohs(stebuf->ste_max_types); j++) 6.186 + printf("%02x ", ntohs(ssids[i*ntohs(stebuf->ste_max_types) +j])); 6.187 + } 6.188 + printf("\n\n"); 6.189 +} 6.190 + 6.191 +void acm_dump_policy_buffer(void *buf, int buflen) { 6.192 + struct acm_policy_buffer *pol = (struct acm_policy_buffer *)buf; 6.193 + 6.194 + printf("\nPolicy dump:\n"); 6.195 + printf("============\n"); 6.196 + printf("Magic = %x.\n", ntohl(pol->magic)); 6.197 + printf("PolVer = %x.\n", ntohl(pol->policyversion)); 6.198 + printf("Len = %x.\n", ntohl(pol->len)); 6.199 + printf("Primary = %s (c=%x, off=%x).\n", 6.200 + ACM_POLICY_NAME(ntohs(pol->primary_policy_code)), 6.201 + ntohs(pol->primary_policy_code), ntohs(pol->primary_buffer_offset)); 6.202 + printf("Secondary = %s (c=%x, off=%x).\n", 6.203 + ACM_POLICY_NAME(ntohs(pol->secondary_policy_code)), 6.204 + ntohs(pol->secondary_policy_code), ntohs(pol->secondary_buffer_offset)); 6.205 + switch (ntohs(pol->primary_policy_code)) { 6.206 + case ACM_CHINESE_WALL_POLICY: 6.207 + acm_dump_chinesewall_buffer(buf+ntohs(pol->primary_buffer_offset), 6.208 + ntohl(pol->len) - ntohs(pol->primary_buffer_offset)); 6.209 + break; 6.210 + case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY: 6.211 + acm_dump_ste_buffer(buf+ntohs(pol->primary_buffer_offset), 6.212 + ntohl(pol->len) - ntohs(pol->primary_buffer_offset)); 6.213 + break; 6.214 + case ACM_NULL_POLICY: 6.215 + printf("Primary policy is NULL Policy (n/a).\n"); 6.216 + break; 6.217 + default: 6.218 + printf("UNKNOWN POLICY!\n"); 6.219 + } 6.220 + switch (ntohs(pol->secondary_policy_code)) { 6.221 + case ACM_CHINESE_WALL_POLICY: 6.222 + acm_dump_chinesewall_buffer(buf+ntohs(pol->secondary_buffer_offset), 6.223 + ntohl(pol->len) - ntohs(pol->secondary_buffer_offset)); 6.224 + break; 6.225 + case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY: 6.226 + acm_dump_ste_buffer(buf+ntohs(pol->secondary_buffer_offset), 6.227 + ntohl(pol->len) - ntohs(pol->secondary_buffer_offset)); 6.228 + break; 6.229 + case ACM_NULL_POLICY: 6.230 + printf("Secondary policy is NULL Policy (n/a).\n"); 6.231 + break; 6.232 + default: 6.233 + printf("UNKNOWN POLICY!\n"); 6.234 + } 6.235 + printf("\nPolicy dump End.\n\n"); 6.236 +} 6.237 + 6.238 +/*************************** set policy ****************************/ 6.239 + 6.240 +int acm_domain_set_chwallpolicy(void *bufstart, int buflen) { 6.241 +#define CWALL_MAX_SSIDREFS 5 6.242 +#define CWALL_MAX_TYPES 10 6.243 +#define CWALL_MAX_CONFLICTSETS 2 6.244 + 6.245 + struct acm_chwall_policy_buffer *chwall_bin_pol = (struct acm_chwall_policy_buffer *)bufstart; 6.246 + domaintype_t *ssidrefs, *conflicts; 6.247 + int ret = 0; 6.248 + int i,j; 6.249 + 6.250 + chwall_bin_pol->chwall_max_types = htons(CWALL_MAX_TYPES); 6.251 + chwall_bin_pol->chwall_max_ssidrefs = htons(CWALL_MAX_SSIDREFS); 6.252 + chwall_bin_pol->policy_code = htons(ACM_CHINESE_WALL_POLICY); 6.253 + chwall_bin_pol->chwall_ssid_offset = htons(sizeof(struct acm_chwall_policy_buffer)); 6.254 + chwall_bin_pol->chwall_max_conflictsets = htons(CWALL_MAX_CONFLICTSETS); 6.255 + chwall_bin_pol->chwall_conflict_sets_offset = 6.256 + htons( 6.257 + ntohs(chwall_bin_pol->chwall_ssid_offset) + 6.258 + sizeof(domaintype_t)*CWALL_MAX_SSIDREFS*CWALL_MAX_TYPES); 6.259 + chwall_bin_pol->chwall_running_types_offset = 0; /* not set */ 6.260 + chwall_bin_pol->chwall_conflict_aggregate_offset = 0; /* not set */ 6.261 + ret += sizeof(struct acm_chwall_policy_buffer); 6.262 + /* now push example ssids into the buffer (max_ssidrefs x max_types entries) */ 6.263 + /* check buffer size */ 6.264 + if ((buflen - ret) < (CWALL_MAX_TYPES*CWALL_MAX_SSIDREFS*sizeof(domaintype_t))) 6.265 + return -1; /* not enough space */ 6.266 + 6.267 + ssidrefs = (domaintype_t *)(bufstart+ntohs(chwall_bin_pol->chwall_ssid_offset)); 6.268 + for(i=0; i< CWALL_MAX_SSIDREFS; i++) { 6.269 + for (j=0; j< CWALL_MAX_TYPES; j++) 6.270 + ssidrefs[i*CWALL_MAX_TYPES + j] = htons(0); 6.271 + /* here, set type i for ssidref i; generally, a ssidref can have multiple chwall types */ 6.272 + if (i < CWALL_MAX_SSIDREFS) 6.273 + ssidrefs[i*CWALL_MAX_TYPES + i] = htons(1); 6.274 + } 6.275 + ret += CWALL_MAX_TYPES*CWALL_MAX_SSIDREFS*sizeof(domaintype_t); 6.276 + if ((buflen - ret) < (CWALL_MAX_CONFLICTSETS*CWALL_MAX_TYPES*sizeof(domaintype_t))) 6.277 + return -1; /* not enough space */ 6.278 + 6.279 + /* now the chinese wall policy conflict sets*/ 6.280 + conflicts = (domaintype_t *)(bufstart + 6.281 + ntohs(chwall_bin_pol->chwall_conflict_sets_offset)); 6.282 + memset((void *)conflicts, 0, CWALL_MAX_CONFLICTSETS*CWALL_MAX_TYPES*sizeof(domaintype_t)); 6.283 + /* just 1 conflict set [0]={2,3}, [1]={0,5,6} */ 6.284 + if (CWALL_MAX_TYPES > 3) { 6.285 + conflicts[2] = htons(1); conflicts[3] = htons(1); /* {2,3} */ 6.286 + conflicts[CWALL_MAX_TYPES] = htons(1); conflicts[CWALL_MAX_TYPES+5] = htons(1); 6.287 + conflicts[CWALL_MAX_TYPES+6] = htons(1);/* {0,5,6} */ 6.288 + } 6.289 + ret += sizeof(domaintype_t)*CWALL_MAX_CONFLICTSETS*CWALL_MAX_TYPES; 6.290 + return ret; 6.291 +} 6.292 + 6.293 +int acm_domain_set_stepolicy(void *bufstart, int buflen) { 6.294 +#define STE_MAX_SSIDREFS 5 6.295 +#define STE_MAX_TYPES 5 6.296 + 6.297 + struct acm_ste_policy_buffer *ste_bin_pol = (struct acm_ste_policy_buffer *)bufstart; 6.298 + domaintype_t *ssidrefs; 6.299 + int i,j, ret = 0; 6.300 + 6.301 + ste_bin_pol->ste_max_types = htons(STE_MAX_TYPES); 6.302 + ste_bin_pol->ste_max_ssidrefs = htons(STE_MAX_SSIDREFS); 6.303 + ste_bin_pol->policy_code = htons(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY); 6.304 + ste_bin_pol->ste_ssid_offset = htons(sizeof(struct acm_ste_policy_buffer)); 6.305 + ret += sizeof(struct acm_ste_policy_buffer); 6.306 + /* check buffer size */ 6.307 + if ((buflen - ret) < (STE_MAX_TYPES*STE_MAX_SSIDREFS*sizeof(domaintype_t))) 6.308 + return -1; /* not enough space */ 6.309 + 6.310 + ssidrefs = (domaintype_t *)(bufstart+ntohs(ste_bin_pol->ste_ssid_offset)); 6.311 + for(i=0; i< STE_MAX_SSIDREFS; i++) { 6.312 + for (j=0; j< STE_MAX_TYPES; j++) 6.313 + ssidrefs[i*STE_MAX_TYPES + j] = htons(0); 6.314 + /* set type i in ssidref 0 and ssidref i */ 6.315 + ssidrefs[i] = htons(1); /* ssidref 0 has all types set */ 6.316 + if (i < STE_MAX_SSIDREFS) 6.317 + ssidrefs[i*STE_MAX_TYPES + i] = htons(1); 6.318 + } 6.319 + ret += STE_MAX_TYPES*STE_MAX_SSIDREFS*sizeof(domaintype_t); 6.320 + return ret; 6.321 +} 6.322 + 6.323 +#define MAX_PUSH_BUFFER 16384 6.324 +u8 push_buffer[MAX_PUSH_BUFFER]; 6.325 + 6.326 +int acm_domain_setpolicy(int xc_handle) 6.327 +{ 6.328 + int ret; 6.329 + struct acm_policy_buffer *bin_pol; 6.330 + policy_op_t op; 6.331 + 6.332 + /* future: read policy from file and set it */ 6.333 + bin_pol = (struct acm_policy_buffer *)push_buffer; 6.334 + bin_pol->magic = htonl(ACM_MAGIC); 6.335 + bin_pol->policyversion = htonl(POLICY_INTERFACE_VERSION); 6.336 + bin_pol->primary_policy_code = htons(ACM_CHINESE_WALL_POLICY); 6.337 + bin_pol->secondary_policy_code = htons(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY); 6.338 + 6.339 + bin_pol->len = htonl(sizeof(struct acm_policy_buffer)); 6.340 + bin_pol->primary_buffer_offset = htons(ntohl(bin_pol->len)); 6.341 + ret = acm_domain_set_chwallpolicy(push_buffer + ntohs(bin_pol->primary_buffer_offset), 6.342 + MAX_PUSH_BUFFER - ntohs(bin_pol->primary_buffer_offset)); 6.343 + if (ret < 0) { 6.344 + printf("ERROR creating chwallpolicy buffer.\n"); 6.345 + return -1; 6.346 + } 6.347 + bin_pol->len = htonl(ntohl(bin_pol->len) + ret); 6.348 + bin_pol->secondary_buffer_offset = htons(ntohl(bin_pol->len)); 6.349 + ret = acm_domain_set_stepolicy(push_buffer + ntohs(bin_pol->secondary_buffer_offset), 6.350 + MAX_PUSH_BUFFER - ntohs(bin_pol->secondary_buffer_offset)); 6.351 + if (ret < 0) { 6.352 + printf("ERROR creating chwallpolicy buffer.\n"); 6.353 + return -1; 6.354 + } 6.355 + bin_pol->len = htonl(ntohl(bin_pol->len) + ret); 6.356 + 6.357 + /* dump it and then push it down into xen/acm */ 6.358 + acm_dump_policy_buffer(push_buffer, ntohl(bin_pol->len)); 6.359 + op.cmd = POLICY_SETPOLICY; 6.360 + op.u.setpolicy.pushcache = (void *)push_buffer; 6.361 + op.u.setpolicy.pushcache_size = ntohl(bin_pol->len); 6.362 + op.u.setpolicy.policy_type = ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY; 6.363 + ret = do_policy_op(xc_handle, &op); 6.364 + 6.365 + if (ret) 6.366 + printf("ERROR setting policy. Use 'xm dmesg' to see details.\n"); 6.367 + else 6.368 + printf("Successfully changed policy.\n"); 6.369 + return ret; 6.370 +} 6.371 + 6.372 +/******************************* get policy ******************************/ 6.373 + 6.374 +#define PULL_CACHE_SIZE 8192 6.375 +u8 pull_buffer[PULL_CACHE_SIZE]; 6.376 +int acm_domain_getpolicy(int xc_handle) 6.377 +{ 6.378 + policy_op_t op; 6.379 + int ret; 6.380 + 6.381 + memset(pull_buffer, 0x00, sizeof(pull_buffer)); 6.382 + op.cmd = POLICY_GETPOLICY; 6.383 + op.u.getpolicy.pullcache = (void *)pull_buffer; 6.384 + op.u.getpolicy.pullcache_size = sizeof(pull_buffer); 6.385 + ret = do_policy_op(xc_handle, &op); 6.386 + /* dump policy */ 6.387 + acm_dump_policy_buffer(pull_buffer, sizeof(pull_buffer)); 6.388 + return ret; 6.389 +} 6.390 + 6.391 +/************************ load binary policy ******************************/ 6.392 + 6.393 +int acm_domain_loadpolicy(int xc_handle, 6.394 + const char *filename) 6.395 +{ 6.396 + struct stat mystat; 6.397 + int ret, fd; 6.398 + off_t len; 6.399 + u8 *buffer; 6.400 + 6.401 + if ((ret = stat(filename, &mystat))) { 6.402 + printf("File %s not found.\n",filename); 6.403 + goto out; 6.404 + } 6.405 + 6.406 + len = mystat.st_size; 6.407 + if ((buffer = malloc(len)) == NULL) { 6.408 + ret = -ENOMEM; 6.409 + goto out; 6.410 + } 6.411 + if ((fd = open(filename, O_RDONLY)) <= 0) { 6.412 + ret = -ENOENT; 6.413 + printf("File %s not found.\n",filename); 6.414 + goto free_out; 6.415 + } 6.416 + if (len == read(fd, buffer, len)) { 6.417 + policy_op_t op; 6.418 + /* dump it and then push it down into xen/acm */ 6.419 + acm_dump_policy_buffer(buffer, len); 6.420 + op.cmd = POLICY_SETPOLICY; 6.421 + op.u.setpolicy.pushcache = (void *)buffer; 6.422 + op.u.setpolicy.pushcache_size = len; 6.423 + op.u.setpolicy.policy_type = ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY; 6.424 + ret = do_policy_op(xc_handle, &op); 6.425 + 6.426 + if (ret) 6.427 + printf("ERROR setting policy. Use 'xm dmesg' to see details.\n"); 6.428 + else 6.429 + printf("Successfully changed policy.\n"); 6.430 + 6.431 + } else { 6.432 + ret = -1; 6.433 + } 6.434 + close(fd); 6.435 + free_out: 6.436 + free(buffer); 6.437 + out: 6.438 + return ret; 6.439 +} 6.440 + 6.441 +/************************ dump hook statistics ******************************/ 6.442 +void 6.443 +dump_ste_stats(struct acm_ste_stats_buffer *ste_stats) 6.444 +{ 6.445 + printf("STE-Policy Security Hook Statistics:\n"); 6.446 + printf("ste: event_channel eval_count = %d\n", ntohl(ste_stats->ec_eval_count)); 6.447 + printf("ste: event_channel denied_count = %d\n", ntohl(ste_stats->ec_denied_count)); 6.448 + printf("ste: event_channel cache_hit_count = %d\n", ntohl(ste_stats->ec_cachehit_count)); 6.449 + printf("ste:\n"); 6.450 + printf("ste: grant_table eval_count = %d\n", ntohl(ste_stats->gt_eval_count)); 6.451 + printf("ste: grant_table denied_count = %d\n", ntohl(ste_stats->gt_denied_count)); 6.452 + printf("ste: grant_table cache_hit_count = %d\n", ntohl(ste_stats->gt_cachehit_count)); 6.453 +} 6.454 + 6.455 +#define PULL_STATS_SIZE 8192 6.456 +int acm_domain_dumpstats(int xc_handle) 6.457 +{ 6.458 + u8 stats_buffer[PULL_STATS_SIZE]; 6.459 + policy_op_t op; 6.460 + int ret; 6.461 + struct acm_stats_buffer *stats; 6.462 + 6.463 + memset(stats_buffer, 0x00, sizeof(stats_buffer)); 6.464 + op.cmd = POLICY_DUMPSTATS; 6.465 + op.u.dumpstats.pullcache = (void *)stats_buffer; 6.466 + op.u.dumpstats.pullcache_size = sizeof(stats_buffer); 6.467 + ret = do_policy_op(xc_handle, &op); 6.468 + 6.469 + if (ret < 0) { 6.470 + printf("ERROR dumping policy stats. Use 'xm dmesg' to see details.\n"); 6.471 + return ret; 6.472 + } 6.473 + stats = (struct acm_stats_buffer *)stats_buffer; 6.474 + 6.475 + printf("\nPolicy dump:\n"); 6.476 + printf("============\n"); 6.477 + printf("Magic = %x.\n", ntohl(stats->magic)); 6.478 + printf("PolVer = %x.\n", ntohl(stats->policyversion)); 6.479 + printf("Len = %x.\n", ntohl(stats->len)); 6.480 + 6.481 + switch(ntohs(stats->primary_policy_code)) { 6.482 + case ACM_NULL_POLICY: 6.483 + printf("NULL Policy: No statistics apply.\n"); 6.484 + break; 6.485 + case ACM_CHINESE_WALL_POLICY: 6.486 + printf("Chinese Wall Policy: No statistics apply.\n"); 6.487 + break; 6.488 + case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY: 6.489 + dump_ste_stats((struct acm_ste_stats_buffer *)(stats_buffer + ntohs(stats->primary_stats_offset))); 6.490 + break; 6.491 + default: 6.492 + printf("UNKNOWN PRIMARY POLICY ERROR!\n"); 6.493 + } 6.494 + switch(ntohs(stats->secondary_policy_code)) { 6.495 + case ACM_NULL_POLICY: 6.496 + printf("NULL Policy: No statistics apply.\n"); 6.497 + break; 6.498 + case ACM_CHINESE_WALL_POLICY: 6.499 + printf("Chinese Wall Policy: No statistics apply.\n"); 6.500 + break; 6.501 + case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY: 6.502 + dump_ste_stats((struct acm_ste_stats_buffer *)(stats_buffer + ntohs(stats->secondary_stats_offset))); 6.503 + break; 6.504 + default: 6.505 + printf("UNKNOWN SECONDARY POLICY ERROR!\n"); 6.506 + } 6.507 + return ret; 6.508 +} 6.509 + 6.510 +/***************************** main **************************************/ 6.511 + 6.512 +void 6.513 +usage(char *progname){ 6.514 + printf("Use: %s \n" 6.515 + "\t setpolicy\n" 6.516 + "\t getpolicy\n" 6.517 + "\t dumpstats\n" 6.518 + "\t loadpolicy <binary policy file>\n", progname); 6.519 + exit(-1); 6.520 +} 6.521 + 6.522 +int 6.523 +main(int argc, char **argv) { 6.524 + 6.525 + int policycmd_fd; 6.526 + 6.527 + if (argc < 2) 6.528 + usage(argv[0]); 6.529 + 6.530 + if ((policycmd_fd = open("/proc/xen/privcmd", O_RDONLY)) <= 0) { 6.531 + printf("ERROR: Could not open xen policycmd device!\n"); 6.532 + exit(-1); 6.533 + } 6.534 + 6.535 + if (!strcmp(argv[1], "setpolicy")) { 6.536 + if (argc != 2) 6.537 + usage(argv[0]); 6.538 + acm_domain_setpolicy(policycmd_fd); 6.539 + 6.540 + } else if (!strcmp(argv[1], "getpolicy")) { 6.541 + if (argc != 2) 6.542 + usage(argv[0]); 6.543 + acm_domain_getpolicy(policycmd_fd); 6.544 + 6.545 + } else if (!strcmp(argv[1], "loadpolicy")) { 6.546 + if (argc != 3) 6.547 + usage(argv[0]); 6.548 + acm_domain_loadpolicy(policycmd_fd, argv[2]); 6.549 + 6.550 + } else if (!strcmp(argv[1], "dumpstats")) { 6.551 + if (argc != 2) 6.552 + usage(argv[0]); 6.553 + acm_domain_dumpstats(policycmd_fd); 6.554 + 6.555 + } else 6.556 + usage(argv[0]); 6.557 + 6.558 + close(policycmd_fd); 6.559 + return 0; 6.560 +}
7.1 --- a/tools/python/xen/lowlevel/xc/xc.c Sun Jun 19 17:05:55 2005 +0000 7.2 +++ b/tools/python/xen/lowlevel/xc/xc.c Mon Jun 20 22:28:08 2005 +0000 7.3 @@ -78,13 +78,14 @@ static PyObject *pyxc_domain_create(PyOb 7.4 7.5 u32 dom = 0; 7.6 int ret; 7.7 + u32 ssidref = 0xFFFFFFFF; 7.8 7.9 - static char *kwd_list[] = { "dom", NULL }; 7.10 + static char *kwd_list[] = { "dom", "ssidref", NULL }; 7.11 7.12 - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &dom)) 7.13 + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list, &dom, &ssidref)) 7.14 return NULL; 7.15 7.16 - if ( (ret = xc_domain_create(xc->xc_handle, &dom)) < 0 ) 7.17 + if ( (ret = xc_domain_create(xc->xc_handle, ssidref, &dom)) < 0 ) 7.18 return PyErr_SetFromErrno(xc_error); 7.19 7.20 return PyInt_FromLong(dom); 7.21 @@ -230,7 +231,7 @@ static PyObject *pyxc_domain_getinfo(PyO 7.22 } 7.23 7.24 info_dict = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i" 7.25 - ",s:l,s:L,s:l,s:i}", 7.26 + ",s:l,s:L,s:l,s:i,s:i}", 7.27 "dom", info[i].domid, 7.28 "vcpus", info[i].vcpus, 7.29 "dying", info[i].dying, 7.30 @@ -242,6 +243,7 @@ static PyObject *pyxc_domain_getinfo(PyO 7.31 "mem_kb", info[i].nr_pages*4, 7.32 "cpu_time", info[i].cpu_time, 7.33 "maxmem_kb", info[i].max_memkb, 7.34 + "ssidref", info[i].ssidref, 7.35 "shutdown_reason", info[i].shutdown_reason); 7.36 PyDict_SetItemString( info_dict, "vcpu_to_cpu", vcpu_list ); 7.37 PyDict_SetItemString( info_dict, "cpumap", cpumap_list );
8.1 --- a/tools/python/xen/xend/XendDomainInfo.py Sun Jun 19 17:05:55 2005 +0000 8.2 +++ b/tools/python/xen/xend/XendDomainInfo.py Mon Jun 20 22:28:08 2005 +0000 8.3 @@ -202,7 +202,9 @@ class XendDomainInfo: 8.4 """ 8.5 db = parentdb.addChild(uuid) 8.6 vm = cls(db) 8.7 - id = xc.domain_create() 8.8 + ssidref = int(sxp.child_value(config, 'ssidref')) 8.9 + log.debug('restoring with ssidref='+str(ssidref)) 8.10 + id = xc.domain_create(ssidref = ssidref) 8.11 vm.setdom(id) 8.12 try: 8.13 vm.restore = True 8.14 @@ -241,6 +243,7 @@ class XendDomainInfo: 8.15 self.start_time = None 8.16 self.name = None 8.17 self.memory = None 8.18 + self.ssidref = None 8.19 self.image = None 8.20 8.21 self.channel = None 8.22 @@ -316,6 +319,7 @@ class XendDomainInfo: 8.23 """ 8.24 self.info = info 8.25 self.memory = self.info['mem_kb'] / 1024 8.26 + self.ssidref = self.info['ssidref'] 8.27 8.28 def state_set(self, state): 8.29 self.state_updated.acquire() 8.30 @@ -336,6 +340,7 @@ class XendDomainInfo: 8.31 s += " id=" + str(self.id) 8.32 s += " name=" + self.name 8.33 s += " memory=" + str(self.memory) 8.34 + s += " ssidref=" + str(self.ssidref) 8.35 console = self.getConsole() 8.36 if console: 8.37 s += " console=" + str(console.console_port) 8.38 @@ -398,7 +403,8 @@ class XendDomainInfo: 8.39 sxpr = ['domain', 8.40 ['id', self.id], 8.41 ['name', self.name], 8.42 - ['memory', self.memory] ] 8.43 + ['memory', self.memory], 8.44 + ['ssidref', self.ssidref] ] 8.45 if self.uuid: 8.46 sxpr.append(['uuid', self.uuid]) 8.47 if self.info: 8.48 @@ -533,6 +539,7 @@ class XendDomainInfo: 8.49 self.memory = int(sxp.child_value(config, 'memory')) 8.50 if self.memory is None: 8.51 raise VmError('missing memory size') 8.52 + self.ssidref = int(sxp.child_value(config, 'ssidref')) 8.53 cpu = sxp.child_value(config, 'cpu') 8.54 if self.recreate and self.id and cpu is not None and int(cpu) >= 0: 8.55 xc.domain_pincpu(self.id, 0, 1<<int(cpu)) 8.56 @@ -644,7 +651,7 @@ class XendDomainInfo: 8.57 def show(self): 8.58 """Print virtual machine info. 8.59 """ 8.60 - print "[VM dom=%d name=%s memory=%d" % (self.id, self.name, self.memory) 8.61 + print "[VM dom=%d name=%s memory=%d ssidref=%d" % (self.id, self.name, self.memory, self.ssidref) 8.62 print "image:" 8.63 sxp.show(self.image) 8.64 print "]" 8.65 @@ -660,7 +667,7 @@ class XendDomainInfo: 8.66 cpu = int(sxp.child_value(self.config, 'cpu', '-1')) 8.67 except: 8.68 raise VmError('invalid cpu') 8.69 - id = self.image.initDomain(self.id, self.memory, cpu, self.cpu_weight) 8.70 + id = self.image.initDomain(self.id, self.memory, self.ssidref, cpu, self.cpu_weight) 8.71 log.debug('init_domain> Created domain=%d name=%s memory=%d', 8.72 id, self.name, self.memory) 8.73 self.setdom(id) 8.74 @@ -1011,6 +1018,7 @@ addImageHandlerClass(VmxImageHandler) 8.75 # Ignore the fields we already handle. 8.76 add_config_handler('name', vm_field_ignore) 8.77 add_config_handler('memory', vm_field_ignore) 8.78 +add_config_handler('ssidref', vm_field_ignore) 8.79 add_config_handler('cpu', vm_field_ignore) 8.80 add_config_handler('cpu_weight', vm_field_ignore) 8.81 add_config_handler('console', vm_field_ignore)
9.1 --- a/tools/python/xen/xend/image.py Sun Jun 19 17:05:55 2005 +0000 9.2 +++ b/tools/python/xen/xend/image.py Mon Jun 20 22:28:08 2005 +0000 9.3 @@ -111,7 +111,7 @@ class ImageHandler: 9.4 except OSError, ex: 9.5 log.warning("error removing bootloader file '%s': %s", f, ex) 9.6 9.7 - def initDomain(self, dom, memory, cpu, cpu_weight): 9.8 + def initDomain(self, dom, memory, ssidref, cpu, cpu_weight): 9.9 """Initial domain create. 9.10 9.11 @return domain id 9.12 @@ -119,14 +119,14 @@ class ImageHandler: 9.13 9.14 mem_kb = self.getDomainMemory(memory) 9.15 if not self.vm.restore: 9.16 - dom = xc.domain_create(dom = dom or 0) 9.17 + dom = xc.domain_create(dom = dom or 0, ssidref = ssidref) 9.18 # if bootloader, unlink here. But should go after buildDomain() ? 9.19 if self.vm.bootloader: 9.20 self.unlink(self.kernel) 9.21 self.unlink(self.ramdisk) 9.22 if dom <= 0: 9.23 raise VmError('Creating domain failed: name=%s' % self.vm.name) 9.24 - log.debug("initDomain: cpu=%d mem_kb=%d dom=%d", cpu, mem_kb, dom) 9.25 + log.debug("initDomain: cpu=%d mem_kb=%d ssidref=%d dom=%d", cpu, mem_kb, ssidref, dom) 9.26 # xc.domain_setuuid(dom, uuid) 9.27 xc.domain_setcpuweight(dom, cpu_weight) 9.28 xc.domain_setmaxmem(dom, mem_kb)
10.1 --- a/tools/python/xen/xend/server/SrvDomainDir.py Sun Jun 19 17:05:55 2005 +0000 10.2 +++ b/tools/python/xen/xend/server/SrvDomainDir.py Mon Jun 20 22:28:08 2005 +0000 10.3 @@ -142,6 +142,7 @@ class SrvDomainDir(SrvDir): 10.4 % (url, d.name, d.name)) 10.5 req.write('id=%s' % d.id) 10.6 req.write('memory=%d'% d.memory) 10.7 + req.write('ssidref=%d'% d.ssidref) 10.8 req.write('</li>') 10.9 req.write('</ul>') 10.10
11.1 --- a/tools/python/xen/xm/create.py Sun Jun 19 17:05:55 2005 +0000 11.2 +++ b/tools/python/xen/xm/create.py Mon Jun 20 22:28:08 2005 +0000 11.3 @@ -120,6 +120,10 @@ gopts.var('memory', val='MEMORY', 11.4 fn=set_int, default=128, 11.5 use="Domain memory in MB.") 11.6 11.7 +gopts.var('ssidref', val='SSIDREF', 11.8 + fn=set_u32, default=0xffffffff, 11.9 + use="Security Identifier.") 11.10 + 11.11 gopts.var('maxmem', val='MEMORY', 11.12 fn=set_int, default=None, 11.13 use="Maximum domain memory in MB.") 11.14 @@ -405,7 +409,8 @@ def make_config(opts, vals): 11.15 11.16 config = ['vm', 11.17 ['name', vals.name ], 11.18 - ['memory', vals.memory ]] 11.19 + ['memory', vals.memory ], 11.20 + ['ssidref', vals.ssidref ]] 11.21 if vals.maxmem: 11.22 config.append(['maxmem', vals.maxmem]) 11.23 if vals.cpu is not None:
12.1 --- a/tools/python/xen/xm/main.py Sun Jun 19 17:05:55 2005 +0000 12.2 +++ b/tools/python/xen/xm/main.py Mon Jun 20 22:28:08 2005 +0000 12.3 @@ -383,7 +383,7 @@ class ProgList(Prog): 12.4 self.brief_list(doms) 12.5 12.6 def brief_list(self, doms): 12.7 - print 'Name Id Mem(MB) CPU VCPU(s) State Time(s) Console' 12.8 + print 'Name Id Mem(MB) CPU VCPU(s) State Time(s) Console SSID-REF' 12.9 for dom in doms: 12.10 info = server.xend_domain(dom) 12.11 d = {} 12.12 @@ -399,8 +399,12 @@ class ProgList(Prog): 12.13 d['port'] = sxp.child_value(console, 'console_port') 12.14 else: 12.15 d['port'] = '' 12.16 - print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3d %(vcpus)5d %(state)5s %(cpu_time)7.1f %(port)4s" 12.17 - % d) 12.18 + if ((int(sxp.child_value(info, 'ssidref', '-1'))) != -1): 12.19 + d['ssidref1'] = int(sxp.child_value(info, 'ssidref', '-1')) & 0xffff 12.20 + d['ssidref2'] = (int(sxp.child_value(info, 'ssidref', '-1')) >> 16) & 0xffff 12.21 + print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3d %(vcpus)5d %(state)5s %(cpu_time)7.1f %(port)4s s:%(ssidref2)02x/p:%(ssidref1)02x" % d) 12.22 + else: 12.23 + print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3d %(vcpus)5d %(state)5s %(cpu_time)7.1f %(port)4s default" % d) 12.24 12.25 def show_vcpus(self, doms): 12.26 print 'Name Id VCPU CPU CPUMAP'
13.1 --- a/tools/python/xen/xm/opts.py Sun Jun 19 17:05:55 2005 +0000 13.2 +++ b/tools/python/xen/xm/opts.py Mon Jun 20 22:28:08 2005 +0000 13.3 @@ -451,6 +451,13 @@ def set_bool(opt, k, v): 13.4 else: 13.5 opt.opts.err('Invalid value:' +v) 13.6 13.7 +def set_u32(opt, k, v): 13.8 + """Set an option to an u32 value.""" 13.9 + try: 13.10 + v = u32(v) 13.11 + except: 13.12 + opt.opts.err('Invalid value: ' + str(v)) 13.13 + opt.set(v) 13.14 13.15 def set_value(opt, k, v): 13.16 """Set an option to a value."""
14.1 --- a/xen/Makefile Sun Jun 19 17:05:55 2005 +0000 14.2 +++ b/xen/Makefile Mon Jun 20 22:28:08 2005 +0000 14.3 @@ -46,6 +46,7 @@ clean: delete-unfresh-files 14.4 $(MAKE) -C tools clean 14.5 $(MAKE) -C common clean 14.6 $(MAKE) -C drivers clean 14.7 + $(MAKE) -C acm clean 14.8 $(MAKE) -C arch/$(TARGET_ARCH) clean 14.9 rm -f include/asm *.o $(TARGET)* *~ core 14.10 rm -f include/asm-*/asm-offsets.h 14.11 @@ -58,6 +59,7 @@ clean: delete-unfresh-files 14.12 $(MAKE) include/asm-$(TARGET_ARCH)/asm-offsets.h 14.13 $(MAKE) -C common 14.14 $(MAKE) -C drivers 14.15 + $(MAKE) -C acm 14.16 $(MAKE) -C arch/$(TARGET_ARCH) 14.17 14.18 # drivers/char/console.o may contain static banner/compile info. Blow it away. 14.19 @@ -109,7 +111,7 @@ include/asm-$(TARGET_ARCH)/asm-offsets.h 14.20 14.21 .PHONY: default debug install dist clean delete-unfresh-files TAGS tags 14.22 14.23 -SUBDIRS = arch/$(TARGET_ARCH) common drivers 14.24 +SUBDIRS = acm arch/$(TARGET_ARCH) common drivers 14.25 define all_sources 14.26 ( find include/asm-$(TARGET_ARCH) -name SCCS -prune -o -name '*.h' -print; \ 14.27 find include -type d -name SCCS -prune -o \( -name "asm-*" -o \
15.1 --- a/xen/Rules.mk Sun Jun 19 17:05:55 2005 +0000 15.2 +++ b/xen/Rules.mk Mon Jun 20 22:28:08 2005 +0000 15.3 @@ -35,6 +35,7 @@ OBJS += $(patsubst %.c,%.o,$(C_SRCS)) 15.4 ALL_OBJS := $(BASEDIR)/common/common.o 15.5 ALL_OBJS += $(BASEDIR)/drivers/char/driver.o 15.6 ALL_OBJS += $(BASEDIR)/drivers/acpi/driver.o 15.7 +ALL_OBJS += $(BASEDIR)/acm/acm.o 15.8 ALL_OBJS += $(BASEDIR)/arch/$(TARGET_ARCH)/arch.o 15.9 15.10
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/xen/acm/Makefile Mon Jun 20 22:28:08 2005 +0000 16.3 @@ -0,0 +1,15 @@ 16.4 + 16.5 +include $(BASEDIR)/Rules.mk 16.6 +OBJS = acm_core.o 16.7 +OBJS += acm_policy.o 16.8 +OBJS += acm_simple_type_enforcement_hooks.o 16.9 +OBJS += acm_chinesewall_hooks.o 16.10 +OBJS += acm_null_hooks.o 16.11 + 16.12 +default: acm.o 16.13 + 16.14 +acm.o: $(OBJS) 16.15 + $(LD) $(LDFLAGS) -r -o acm.o $(OBJS) 16.16 + 16.17 +clean: 16.18 + rm -f *.o *~ core
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/xen/acm/acm_chinesewall_hooks.c Mon Jun 20 22:28:08 2005 +0000 17.3 @@ -0,0 +1,503 @@ 17.4 +/**************************************************************** 17.5 + * acm_chinesewall_hooks.c 17.6 + * 17.7 + * Copyright (C) 2005 IBM Corporation 17.8 + * 17.9 + * Author: 17.10 + * Reiner Sailer <sailer@watson.ibm.com> 17.11 + * 17.12 + * Contributions: 17.13 + * Stefan Berger <stefanb@watson.ibm.com> 17.14 + * 17.15 + * This program is free software; you can redistribute it and/or 17.16 + * modify it under the terms of the GNU General Public License as 17.17 + * published by the Free Software Foundation, version 2 of the 17.18 + * License. 17.19 + * 17.20 + * sHype Chinese Wall Policy for Xen 17.21 + * This code implements the hooks that are called 17.22 + * throughout Xen operations and decides authorization 17.23 + * based on domain types and Chinese Wall conflict type 17.24 + * sets. The CHWALL policy decides if a new domain can be started 17.25 + * based on the types of running domains and the type of the 17.26 + * new domain to be started. If the new domain's type is in 17.27 + * conflict with types of running domains, then this new domain 17.28 + * is not allowed to be created. A domain can have multiple types, 17.29 + * in which case all types of a new domain must be conflict-free 17.30 + * with all types of already running domains. 17.31 + * 17.32 + */ 17.33 +#include <xen/config.h> 17.34 +#include <xen/errno.h> 17.35 +#include <xen/types.h> 17.36 +#include <xen/lib.h> 17.37 +#include <xen/delay.h> 17.38 +#include <xen/sched.h> 17.39 +#include <public/acm.h> 17.40 +#include <asm/atomic.h> 17.41 +#include <acm/acm_core.h> 17.42 +#include <acm/acm_hooks.h> 17.43 +#include <acm/acm_endian.h> 17.44 + 17.45 +/* local cache structures for chinese wall policy */ 17.46 +struct chwall_binary_policy chwall_bin_pol; 17.47 + 17.48 +/* 17.49 + * Initializing chinese wall policy (will be filled by policy partition 17.50 + * using setpolicy command) 17.51 + */ 17.52 +int acm_init_chwall_policy(void) 17.53 +{ 17.54 + /* minimal startup policy; policy write-locked already */ 17.55 + chwall_bin_pol.max_types = 1; 17.56 + chwall_bin_pol.max_ssidrefs = 1; 17.57 + chwall_bin_pol.max_conflictsets = 1; 17.58 + chwall_bin_pol.ssidrefs = (domaintype_t *)xmalloc_array(domaintype_t, chwall_bin_pol.max_ssidrefs*chwall_bin_pol.max_types); 17.59 + chwall_bin_pol.conflict_sets = (domaintype_t *)xmalloc_array(domaintype_t, chwall_bin_pol.max_conflictsets*chwall_bin_pol.max_types); 17.60 + chwall_bin_pol.running_types = (domaintype_t *)xmalloc_array(domaintype_t, chwall_bin_pol.max_types); 17.61 + chwall_bin_pol.conflict_aggregate_set = (domaintype_t *)xmalloc_array(domaintype_t, chwall_bin_pol.max_types); 17.62 + 17.63 + if ((chwall_bin_pol.conflict_sets == NULL) || (chwall_bin_pol.running_types == NULL) || 17.64 + (chwall_bin_pol.ssidrefs == NULL) || (chwall_bin_pol.conflict_aggregate_set == NULL)) 17.65 + return ACM_INIT_SSID_ERROR; 17.66 + 17.67 + /* initialize state */ 17.68 + memset((void *)chwall_bin_pol.ssidrefs, 0, chwall_bin_pol.max_ssidrefs*chwall_bin_pol.max_types*sizeof(domaintype_t)); 17.69 + memset((void *)chwall_bin_pol.conflict_sets, 0, chwall_bin_pol.max_conflictsets*chwall_bin_pol.max_types*sizeof(domaintype_t)); 17.70 + memset((void *)chwall_bin_pol.running_types, 0, chwall_bin_pol.max_types*sizeof(domaintype_t)); 17.71 + memset((void *)chwall_bin_pol.conflict_aggregate_set, 0, chwall_bin_pol.max_types*sizeof(domaintype_t)); 17.72 + return ACM_OK; 17.73 +} 17.74 + 17.75 +static int 17.76 +chwall_init_domain_ssid(void **chwall_ssid, ssidref_t ssidref) 17.77 +{ 17.78 + struct chwall_ssid *chwall_ssidp = xmalloc(struct chwall_ssid); 17.79 + traceprintk("%s.\n", __func__); 17.80 + if (chwall_ssidp == NULL) 17.81 + return ACM_INIT_SSID_ERROR; 17.82 + /* 17.83 + * depending on wheter chwall is primary or secondary, get the respective 17.84 + * part of the global ssidref (same way we'll get the partial ssid pointer) 17.85 + */ 17.86 + chwall_ssidp->chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref); 17.87 + if (chwall_ssidp->chwall_ssidref >= chwall_bin_pol.max_ssidrefs) { 17.88 + printkd("%s: ERROR chwall_ssidref(%x) > max(%x).\n", 17.89 + __func__, chwall_ssidp->chwall_ssidref, chwall_bin_pol.max_ssidrefs-1); 17.90 + xfree(chwall_ssidp); 17.91 + return ACM_INIT_SSID_ERROR; 17.92 + } 17.93 + (*chwall_ssid) = chwall_ssidp; 17.94 + printkd("%s: determined chwall_ssidref to %x.\n", 17.95 + __func__, chwall_ssidp->chwall_ssidref); 17.96 + return ACM_OK; 17.97 +} 17.98 + 17.99 +static void 17.100 +chwall_free_domain_ssid(void *chwall_ssid) 17.101 +{ 17.102 + traceprintk("%s.\n", __func__); 17.103 + if (chwall_ssid != NULL) 17.104 + xfree(chwall_ssid); 17.105 + return; 17.106 +} 17.107 + 17.108 + 17.109 +/* dump chinese wall cache; policy read-locked already */ 17.110 +static int 17.111 +chwall_dump_policy(u8 *buf, u16 buf_size) { 17.112 + struct acm_chwall_policy_buffer *chwall_buf = (struct acm_chwall_policy_buffer *)buf; 17.113 + int ret = 0; 17.114 + 17.115 + chwall_buf->chwall_max_types = htons(chwall_bin_pol.max_types); 17.116 + chwall_buf->chwall_max_ssidrefs = htons(chwall_bin_pol.max_ssidrefs); 17.117 + chwall_buf->policy_code = htons(ACM_CHINESE_WALL_POLICY); 17.118 + chwall_buf->chwall_ssid_offset = htons(sizeof(struct acm_chwall_policy_buffer)); 17.119 + chwall_buf->chwall_max_conflictsets = htons(chwall_bin_pol.max_conflictsets); 17.120 + chwall_buf->chwall_conflict_sets_offset = 17.121 + htons( 17.122 + ntohs(chwall_buf->chwall_ssid_offset) + 17.123 + sizeof(domaintype_t) * chwall_bin_pol.max_ssidrefs * 17.124 + chwall_bin_pol.max_types); 17.125 + 17.126 + chwall_buf->chwall_running_types_offset = 17.127 + htons( 17.128 + ntohs(chwall_buf->chwall_conflict_sets_offset) + 17.129 + sizeof(domaintype_t) * chwall_bin_pol.max_conflictsets * 17.130 + chwall_bin_pol.max_types); 17.131 + 17.132 + chwall_buf->chwall_conflict_aggregate_offset = 17.133 + htons( 17.134 + ntohs(chwall_buf->chwall_running_types_offset) + 17.135 + sizeof(domaintype_t) * chwall_bin_pol.max_types); 17.136 + 17.137 + ret = ntohs(chwall_buf->chwall_conflict_aggregate_offset) + 17.138 + sizeof(domaintype_t) * chwall_bin_pol.max_types; 17.139 + 17.140 + /* now copy buffers over */ 17.141 + arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_ssid_offset)), 17.142 + chwall_bin_pol.ssidrefs, 17.143 + chwall_bin_pol.max_ssidrefs * chwall_bin_pol.max_types); 17.144 + 17.145 + arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_conflict_sets_offset)), 17.146 + chwall_bin_pol.conflict_sets, 17.147 + chwall_bin_pol.max_conflictsets * chwall_bin_pol.max_types); 17.148 + 17.149 + arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_running_types_offset)), 17.150 + chwall_bin_pol.running_types, 17.151 + chwall_bin_pol.max_types); 17.152 + 17.153 + arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_conflict_aggregate_offset)), 17.154 + chwall_bin_pol.conflict_aggregate_set, 17.155 + chwall_bin_pol.max_types); 17.156 + return ret; 17.157 +} 17.158 + 17.159 +/* adapt security state (running_types and conflict_aggregate_set) to all running 17.160 + * domains; chwall_init_state is called when a policy is changed to bring the security 17.161 + * information into a consistent state and to detect violations (return != 0). 17.162 + * from a security point of view, we simulate that all running domains are re-started 17.163 + */ 17.164 +static int 17.165 +chwall_init_state(struct acm_chwall_policy_buffer *chwall_buf, domaintype_t *ssidrefs, domaintype_t *conflict_sets, 17.166 + domaintype_t *running_types, domaintype_t *conflict_aggregate_set) 17.167 +{ 17.168 + int violation = 0, i, j; 17.169 + struct chwall_ssid *chwall_ssid; 17.170 + ssidref_t chwall_ssidref; 17.171 + struct domain **pd; 17.172 + 17.173 + write_lock(&domlist_lock); 17.174 + /* go through all domains and adjust policy as if this domain was started now */ 17.175 + pd = &domain_list; 17.176 + for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) { 17.177 + chwall_ssid = GET_SSIDP(ACM_CHINESE_WALL_POLICY, (struct acm_ssid_domain *)(*pd)->ssid); 17.178 + chwall_ssidref = chwall_ssid->chwall_ssidref; 17.179 + traceprintk("%s: validating policy for domain %x (chwall-REF=%x).\n", 17.180 + __func__, (*pd)->domain_id, chwall_ssidref); 17.181 + /* a) adjust types ref-count for running domains */ 17.182 + for (i=0; i< chwall_buf->chwall_max_types; i++) 17.183 + running_types[i] += 17.184 + ssidrefs[chwall_ssidref*chwall_buf->chwall_max_types + i]; 17.185 + 17.186 + /* b) check for conflict */ 17.187 + for (i=0; i< chwall_buf->chwall_max_types; i++) 17.188 + if (conflict_aggregate_set[i] && 17.189 + ssidrefs[chwall_ssidref*chwall_buf->chwall_max_types + i]) { 17.190 + printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i); 17.191 + violation = 1; 17.192 + goto out; 17.193 + } 17.194 + /* set violation and break out of the loop */ 17.195 + /* c) adapt conflict aggregate set for this domain (notice conflicts) */ 17.196 + for (i=0; i<chwall_buf->chwall_max_conflictsets; i++) { 17.197 + int common = 0; 17.198 + /* check if conflict_set_i and ssidref have common types */ 17.199 + for (j=0; j<chwall_buf->chwall_max_types; j++) 17.200 + if (conflict_sets[i*chwall_buf->chwall_max_types + j] && 17.201 + ssidrefs[chwall_ssidref*chwall_buf->chwall_max_types + j]) { 17.202 + common = 1; 17.203 + break; 17.204 + } 17.205 + if (common == 0) 17.206 + continue; /* try next conflict set */ 17.207 + /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */ 17.208 + for (j=0; j<chwall_buf->chwall_max_types; j++) 17.209 + if (conflict_sets[i*chwall_buf->chwall_max_types + j] && 17.210 + !ssidrefs[chwall_ssidref*chwall_buf->chwall_max_types + j]) 17.211 + conflict_aggregate_set[j]++; 17.212 + } 17.213 + } 17.214 + out: 17.215 + write_unlock(&domlist_lock); 17.216 + return violation; 17.217 + /* returning "violation != 0" means that the currently running set of domains would 17.218 + * not be possible if the new policy had been enforced before starting them; for chinese 17.219 + * wall, this means that the new policy includes at least one conflict set of which 17.220 + * more than one type is currently running */ 17.221 +} 17.222 + 17.223 +static int 17.224 +chwall_set_policy(u8 *buf, u16 buf_size) 17.225 +{ 17.226 + /* policy write-locked already */ 17.227 + struct acm_chwall_policy_buffer *chwall_buf = (struct acm_chwall_policy_buffer *)buf; 17.228 + void *ssids = NULL, *conflict_sets = NULL, *running_types = NULL, *conflict_aggregate_set = NULL; 17.229 + 17.230 + /* rewrite the policy due to endianess */ 17.231 + chwall_buf->policy_code = ntohs(chwall_buf->policy_code); 17.232 + chwall_buf->chwall_max_types = ntohs(chwall_buf->chwall_max_types); 17.233 + chwall_buf->chwall_max_ssidrefs = ntohs(chwall_buf->chwall_max_ssidrefs); 17.234 + chwall_buf->chwall_max_conflictsets = ntohs(chwall_buf->chwall_max_conflictsets); 17.235 + chwall_buf->chwall_ssid_offset = ntohs(chwall_buf->chwall_ssid_offset); 17.236 + chwall_buf->chwall_conflict_sets_offset = ntohs(chwall_buf->chwall_conflict_sets_offset); 17.237 + chwall_buf->chwall_running_types_offset = ntohs(chwall_buf->chwall_running_types_offset); 17.238 + chwall_buf->chwall_conflict_aggregate_offset = ntohs(chwall_buf->chwall_conflict_aggregate_offset); 17.239 + 17.240 + /* 1. allocate new buffers */ 17.241 + ssids = xmalloc_array(domaintype_t, chwall_buf->chwall_max_types*chwall_buf->chwall_max_ssidrefs); 17.242 + conflict_sets = xmalloc_array(domaintype_t, chwall_buf->chwall_max_conflictsets*chwall_buf->chwall_max_types); 17.243 + running_types = xmalloc_array(domaintype_t,chwall_buf->chwall_max_types); 17.244 + conflict_aggregate_set = xmalloc_array(domaintype_t, chwall_buf->chwall_max_types); 17.245 + 17.246 + if ((ssids == NULL)||(conflict_sets == NULL)||(running_types == NULL)||(conflict_aggregate_set == NULL)) 17.247 + goto error_free; 17.248 + 17.249 + /* 2. set new policy */ 17.250 + if (chwall_buf->chwall_ssid_offset + sizeof(domaintype_t) * 17.251 + chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs > buf_size) 17.252 + goto error_free; 17.253 + arrcpy(ssids, buf + chwall_buf->chwall_ssid_offset, 17.254 + sizeof(domaintype_t), 17.255 + chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs); 17.256 + 17.257 + if (chwall_buf->chwall_conflict_sets_offset + sizeof(domaintype_t) * 17.258 + chwall_buf->chwall_max_types * chwall_buf->chwall_max_conflictsets > buf_size) 17.259 + goto error_free; 17.260 + 17.261 + arrcpy(conflict_sets, buf + chwall_buf->chwall_conflict_sets_offset, 17.262 + sizeof(domaintype_t), 17.263 + chwall_buf->chwall_max_types * chwall_buf->chwall_max_conflictsets); 17.264 + 17.265 + /* we also use new state buffers since max_types can change */ 17.266 + memset(running_types, 0, sizeof(domaintype_t)*chwall_buf->chwall_max_types); 17.267 + memset(conflict_aggregate_set, 0, sizeof(domaintype_t)*chwall_buf->chwall_max_types); 17.268 + 17.269 + /* 3. now re-calculate the state for the new policy based on running domains; 17.270 + * this can fail if new policy is conflicting with running domains */ 17.271 + if (chwall_init_state(chwall_buf, ssids, conflict_sets, running_types, conflict_aggregate_set)) { 17.272 + printk("%s: New policy conflicts with running domains. Policy load aborted.\n", __func__); 17.273 + goto error_free; /* new policy conflicts with running domains */ 17.274 + } 17.275 + /* 4. free old policy buffers, replace with new ones */ 17.276 + chwall_bin_pol.max_types = chwall_buf->chwall_max_types; 17.277 + chwall_bin_pol.max_ssidrefs = chwall_buf->chwall_max_ssidrefs; 17.278 + chwall_bin_pol.max_conflictsets = chwall_buf->chwall_max_conflictsets; 17.279 + if (chwall_bin_pol.ssidrefs != NULL) 17.280 + xfree(chwall_bin_pol.ssidrefs); 17.281 + if (chwall_bin_pol.conflict_aggregate_set != NULL) 17.282 + xfree(chwall_bin_pol.conflict_aggregate_set); 17.283 + if (chwall_bin_pol.running_types != NULL) 17.284 + xfree(chwall_bin_pol.running_types); 17.285 + if (chwall_bin_pol.conflict_sets != NULL) 17.286 + xfree(chwall_bin_pol.conflict_sets); 17.287 + chwall_bin_pol.ssidrefs = ssids; 17.288 + chwall_bin_pol.conflict_aggregate_set = conflict_aggregate_set; 17.289 + chwall_bin_pol.running_types = running_types; 17.290 + chwall_bin_pol.conflict_sets = conflict_sets; 17.291 + return ACM_OK; 17.292 + 17.293 +error_free: 17.294 + printk("%s: ERROR setting policy.\n", __func__); 17.295 + if (ssids != NULL) xfree(ssids); 17.296 + if (conflict_sets != NULL) xfree(conflict_sets); 17.297 + if (running_types != NULL) xfree(running_types); 17.298 + if (conflict_aggregate_set != NULL) xfree(conflict_aggregate_set); 17.299 + return -EFAULT; 17.300 +} 17.301 + 17.302 +static int 17.303 +chwall_dump_stats(u8 *buf, u16 len) 17.304 +{ 17.305 + /* no stats for Chinese Wall Policy */ 17.306 + return 0; 17.307 +} 17.308 + 17.309 +/*************************** 17.310 + * Authorization functions 17.311 + ***************************/ 17.312 + 17.313 + 17.314 +/* -------- DOMAIN OPERATION HOOKS -----------*/ 17.315 + 17.316 +static int 17.317 +chwall_pre_domain_create(void *subject_ssid, ssidref_t ssidref) 17.318 +{ 17.319 + ssidref_t chwall_ssidref; 17.320 + int i,j; 17.321 + traceprintk("%s.\n", __func__); 17.322 + 17.323 + read_lock(&acm_bin_pol_rwlock); 17.324 + chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref); 17.325 + if (chwall_ssidref == ACM_DEFAULT_LOCAL_SSID) { 17.326 + printk("%s: ERROR CHWALL SSID is NOT SET but policy enforced.\n", __func__); 17.327 + read_unlock(&acm_bin_pol_rwlock); 17.328 + return ACM_ACCESS_DENIED; /* catching and indicating config error */ 17.329 + } 17.330 + if (chwall_ssidref >= chwall_bin_pol.max_ssidrefs) { 17.331 + printk("%s: ERROR chwall_ssidref > max(%x).\n", 17.332 + __func__, chwall_bin_pol.max_ssidrefs-1); 17.333 + read_unlock(&acm_bin_pol_rwlock); 17.334 + return ACM_ACCESS_DENIED; 17.335 + } 17.336 + /* A: chinese wall check for conflicts */ 17.337 + for (i=0; i< chwall_bin_pol.max_types; i++) 17.338 + if (chwall_bin_pol.conflict_aggregate_set[i] && 17.339 + chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + i]) { 17.340 + printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i); 17.341 + read_unlock(&acm_bin_pol_rwlock); 17.342 + return ACM_ACCESS_DENIED; 17.343 + } 17.344 + 17.345 + /* B: chinese wall conflict set adjustment (so that other 17.346 + * other domains simultaneously created are evaluated against this new set)*/ 17.347 + for (i=0; i<chwall_bin_pol.max_conflictsets; i++) { 17.348 + int common = 0; 17.349 + /* check if conflict_set_i and ssidref have common types */ 17.350 + for (j=0; j<chwall_bin_pol.max_types; j++) 17.351 + if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] && 17.352 + chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) { 17.353 + common = 1; 17.354 + break; 17.355 + } 17.356 + if (common == 0) 17.357 + continue; /* try next conflict set */ 17.358 + /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */ 17.359 + for (j=0; j<chwall_bin_pol.max_types; j++) 17.360 + if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] && 17.361 + !chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) 17.362 + chwall_bin_pol.conflict_aggregate_set[j]++; 17.363 + } 17.364 + read_unlock(&acm_bin_pol_rwlock); 17.365 + return ACM_ACCESS_PERMITTED; 17.366 +} 17.367 + 17.368 +static void 17.369 +chwall_post_domain_create(domid_t domid, ssidref_t ssidref) 17.370 +{ 17.371 + int i,j; 17.372 + ssidref_t chwall_ssidref; 17.373 + traceprintk("%s.\n", __func__); 17.374 + 17.375 + read_lock(&acm_bin_pol_rwlock); 17.376 + chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref); 17.377 + /* adjust types ref-count for running domains */ 17.378 + for (i=0; i< chwall_bin_pol.max_types; i++) 17.379 + chwall_bin_pol.running_types[i] += 17.380 + chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + i]; 17.381 + if (domid) { 17.382 + read_unlock(&acm_bin_pol_rwlock); 17.383 + return; 17.384 + } 17.385 + /* Xen does not call pre-create hook for DOM0; 17.386 + * to consider type conflicts of any domain with DOM0, we need 17.387 + * to adjust the conflict_aggregate for DOM0 here the same way it 17.388 + * is done for non-DOM0 domains in the pre-hook */ 17.389 + printkd("%s: adjusting security state for DOM0 (ssidref=%x, chwall_ssidref=%x).\n", 17.390 + __func__, ssidref, chwall_ssidref); 17.391 + 17.392 + /* chinese wall conflict set adjustment (so that other 17.393 + * other domains simultaneously created are evaluated against this new set)*/ 17.394 + for (i=0; i<chwall_bin_pol.max_conflictsets; i++) { 17.395 + int common = 0; 17.396 + /* check if conflict_set_i and ssidref have common types */ 17.397 + for (j=0; j<chwall_bin_pol.max_types; j++) 17.398 + if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] && 17.399 + chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) { 17.400 + common = 1; 17.401 + break; 17.402 + } 17.403 + if (common == 0) 17.404 + continue; /* try next conflict set */ 17.405 + /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */ 17.406 + for (j=0; j<chwall_bin_pol.max_types; j++) 17.407 + if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] && 17.408 + !chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) 17.409 + chwall_bin_pol.conflict_aggregate_set[j]++; 17.410 + } 17.411 + read_unlock(&acm_bin_pol_rwlock); 17.412 + return; 17.413 +} 17.414 + 17.415 +static void 17.416 +chwall_fail_domain_create(void *subject_ssid, ssidref_t ssidref) 17.417 +{ 17.418 + int i, j; 17.419 + ssidref_t chwall_ssidref; 17.420 + traceprintk("%s.\n", __func__); 17.421 + 17.422 + read_lock(&acm_bin_pol_rwlock); 17.423 + chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref); 17.424 + /* roll-back: re-adjust conflicting types aggregate */ 17.425 + for (i=0; i<chwall_bin_pol.max_conflictsets; i++) { 17.426 + int common = 0; 17.427 + /* check if conflict_set_i and ssidref have common types */ 17.428 + for (j=0; j<chwall_bin_pol.max_types; j++) 17.429 + if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] && 17.430 + chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) { 17.431 + common = 1; 17.432 + break; 17.433 + } 17.434 + if (common == 0) 17.435 + continue; /* try next conflict set, this one does not include any type of chwall_ssidref */ 17.436 + /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */ 17.437 + for (j=0; j<chwall_bin_pol.max_types; j++) 17.438 + if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] && 17.439 + !chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) 17.440 + chwall_bin_pol.conflict_aggregate_set[j]--; 17.441 + } 17.442 + read_unlock(&acm_bin_pol_rwlock); 17.443 +} 17.444 + 17.445 + 17.446 +static void 17.447 +chwall_post_domain_destroy(void *object_ssid, domid_t id) 17.448 +{ 17.449 + int i,j; 17.450 + struct chwall_ssid *chwall_ssidp = 17.451 + GET_SSIDP(ACM_CHINESE_WALL_POLICY, (struct acm_ssid_domain *)object_ssid); 17.452 + ssidref_t chwall_ssidref = chwall_ssidp->chwall_ssidref; 17.453 + 17.454 + traceprintk("%s.\n", __func__); 17.455 + 17.456 + read_lock(&acm_bin_pol_rwlock); 17.457 + /* adjust running types set */ 17.458 + for (i=0; i< chwall_bin_pol.max_types; i++) 17.459 + chwall_bin_pol.running_types[i] -= 17.460 + chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + i]; 17.461 + 17.462 + /* roll-back: re-adjust conflicting types aggregate */ 17.463 + for (i=0; i<chwall_bin_pol.max_conflictsets; i++) { 17.464 + int common = 0; 17.465 + /* check if conflict_set_i and ssidref have common types */ 17.466 + for (j=0; j<chwall_bin_pol.max_types; j++) 17.467 + if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] && 17.468 + chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) { 17.469 + common = 1; 17.470 + break; 17.471 + } 17.472 + if (common == 0) 17.473 + continue; /* try next conflict set, this one does not include any type of chwall_ssidref */ 17.474 + /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */ 17.475 + for (j=0; j<chwall_bin_pol.max_types; j++) 17.476 + if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] && 17.477 + !chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) 17.478 + chwall_bin_pol.conflict_aggregate_set[j]--; 17.479 + } 17.480 + read_unlock(&acm_bin_pol_rwlock); 17.481 + return; 17.482 +} 17.483 + 17.484 +struct acm_operations acm_chinesewall_ops = { 17.485 + /* policy management services */ 17.486 + .init_domain_ssid = chwall_init_domain_ssid, 17.487 + .free_domain_ssid = chwall_free_domain_ssid, 17.488 + .dump_binary_policy = chwall_dump_policy, 17.489 + .set_binary_policy = chwall_set_policy, 17.490 + .dump_statistics = chwall_dump_stats, 17.491 + /* domain management control hooks */ 17.492 + .pre_domain_create = chwall_pre_domain_create, 17.493 + .post_domain_create = chwall_post_domain_create, 17.494 + .fail_domain_create = chwall_fail_domain_create, 17.495 + .post_domain_destroy = chwall_post_domain_destroy, 17.496 + /* event channel control hooks */ 17.497 + .pre_eventchannel_unbound = NULL, 17.498 + .fail_eventchannel_unbound = NULL, 17.499 + .pre_eventchannel_interdomain = NULL, 17.500 + .fail_eventchannel_interdomain = NULL, 17.501 + /* grant table control hooks */ 17.502 + .pre_grant_map_ref = NULL, 17.503 + .fail_grant_map_ref = NULL, 17.504 + .pre_grant_setup = NULL, 17.505 + .fail_grant_setup = NULL, 17.506 +};
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/xen/acm/acm_core.c Mon Jun 20 22:28:08 2005 +0000 18.3 @@ -0,0 +1,205 @@ 18.4 +/**************************************************************** 18.5 + * acm_core.c 18.6 + * 18.7 + * Copyright (C) 2005 IBM Corporation 18.8 + * 18.9 + * Author: 18.10 + * Reiner Sailer <sailer@watson.ibm.com> 18.11 + * 18.12 + * This program is free software; you can redistribute it and/or 18.13 + * modify it under the terms of the GNU General Public License as 18.14 + * published by the Free Software Foundation, version 2 of the 18.15 + * License. 18.16 + * 18.17 + * sHype access control module (ACM) 18.18 + * This file handles initialization of the ACM 18.19 + * as well as initializing/freeing security 18.20 + * identifiers for domains (it calls on active 18.21 + * policy hook functions). 18.22 + * 18.23 + */ 18.24 + 18.25 +#include <xen/config.h> 18.26 +#include <xen/errno.h> 18.27 +#include <xen/types.h> 18.28 +#include <xen/lib.h> 18.29 +#include <xen/delay.h> 18.30 +#include <xen/sched.h> 18.31 +#include <acm/acm_hooks.h> 18.32 +#include <acm/acm_endian.h> 18.33 + 18.34 +/* debug: 18.35 + * include/acm/acm_hooks.h defines a constant ACM_TRACE_MODE; 18.36 + * define/undefine this constant to receive / suppress any 18.37 + * security hook debug output of sHype 18.38 + * 18.39 + * include/public/acm.h defines a constant ACM_DEBUG 18.40 + * define/undefine this constant to receive non-hook-related 18.41 + * debug output. 18.42 + */ 18.43 + 18.44 +/* function prototypes */ 18.45 +void acm_init_chwall_policy(void); 18.46 +void acm_init_ste_policy(void); 18.47 + 18.48 +extern struct acm_operations acm_chinesewall_ops, 18.49 + acm_simple_type_enforcement_ops, acm_null_ops; 18.50 + 18.51 +/* global ops structs called by the hooks */ 18.52 +struct acm_operations *acm_primary_ops = NULL; 18.53 +/* called in hook if-and-only-if primary succeeds */ 18.54 +struct acm_operations *acm_secondary_ops = NULL; 18.55 + 18.56 +/* acm global binary policy (points to 'local' primary and secondary policies */ 18.57 +struct acm_binary_policy acm_bin_pol; 18.58 +/* acm binary policy lock */ 18.59 +rwlock_t acm_bin_pol_rwlock = RW_LOCK_UNLOCKED; 18.60 + 18.61 +/* until we have endian support in Xen, we discover it at runtime */ 18.62 +u8 little_endian = 1; 18.63 +void acm_set_endian(void) 18.64 +{ 18.65 + u32 test = 1; 18.66 + if (*((u8 *)&test) == 1) { 18.67 + printk("ACM module running in LITTLE ENDIAN.\n"); 18.68 + little_endian = 1; 18.69 + } else { 18.70 + printk("ACM module running in BIG ENDIAN.\n"); 18.71 + little_endian = 0; 18.72 + } 18.73 +} 18.74 + 18.75 +/* initialize global security policy for Xen; policy write-locked already */ 18.76 +static void 18.77 +acm_init_binary_policy(void *primary, void *secondary) 18.78 +{ 18.79 + acm_bin_pol.primary_policy_code = 0; 18.80 + acm_bin_pol.secondary_policy_code = 0; 18.81 + acm_bin_pol.primary_binary_policy = primary; 18.82 + acm_bin_pol.secondary_binary_policy = secondary; 18.83 +} 18.84 + 18.85 +int 18.86 +acm_init(void) 18.87 +{ 18.88 + int ret = -EINVAL; 18.89 + 18.90 + acm_set_endian(); 18.91 + write_lock(&acm_bin_pol_rwlock); 18.92 + 18.93 + if (ACM_USE_SECURITY_POLICY == ACM_CHINESE_WALL_POLICY) { 18.94 + acm_init_binary_policy(NULL, NULL); 18.95 + acm_init_chwall_policy(); 18.96 + acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY; 18.97 + acm_primary_ops = &acm_chinesewall_ops; 18.98 + acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY; 18.99 + acm_secondary_ops = &acm_null_ops; 18.100 + ret = ACM_OK; 18.101 + } else if (ACM_USE_SECURITY_POLICY == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) { 18.102 + acm_init_binary_policy(NULL, NULL); 18.103 + acm_init_ste_policy(); 18.104 + acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY; 18.105 + acm_primary_ops = &acm_simple_type_enforcement_ops; 18.106 + acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY; 18.107 + acm_secondary_ops = &acm_null_ops; 18.108 + ret = ACM_OK; 18.109 + } else if (ACM_USE_SECURITY_POLICY == ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) { 18.110 + acm_init_binary_policy(NULL, NULL); 18.111 + acm_init_chwall_policy(); 18.112 + acm_init_ste_policy(); 18.113 + acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY; 18.114 + acm_primary_ops = &acm_chinesewall_ops; 18.115 + acm_bin_pol.secondary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY; 18.116 + acm_secondary_ops = &acm_simple_type_enforcement_ops; 18.117 + ret = ACM_OK; 18.118 + } else if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) { 18.119 + acm_init_binary_policy(NULL, NULL); 18.120 + acm_bin_pol.primary_policy_code = ACM_NULL_POLICY; 18.121 + acm_primary_ops = &acm_null_ops; 18.122 + acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY; 18.123 + acm_secondary_ops = &acm_null_ops; 18.124 + ret = ACM_OK; 18.125 + } 18.126 + write_unlock(&acm_bin_pol_rwlock); 18.127 + 18.128 + if (ret != ACM_OK) 18.129 + return -EINVAL; 18.130 + printk("%s: Enforcing Primary %s, Secondary %s.\n", __func__, 18.131 + ACM_POLICY_NAME(acm_bin_pol.primary_policy_code), ACM_POLICY_NAME(acm_bin_pol.secondary_policy_code)); 18.132 + return ACM_OK; 18.133 +} 18.134 + 18.135 + 18.136 +int 18.137 +acm_init_domain_ssid(domid_t id, ssidref_t ssidref) 18.138 +{ 18.139 + struct acm_ssid_domain *ssid; 18.140 + struct domain *subj = find_domain_by_id(id); 18.141 + int ret1, ret2; 18.142 + 18.143 + if (subj == NULL) { 18.144 + printk("%s: ACM_NULL_POINTER ERROR (id=%x).\n", __func__, id); 18.145 + return ACM_NULL_POINTER_ERROR; 18.146 + } 18.147 + if ((ssid = xmalloc(struct acm_ssid_domain)) == NULL) 18.148 + return ACM_INIT_SSID_ERROR; 18.149 + 18.150 + ssid->datatype = DOMAIN; 18.151 + ssid->subject = subj; 18.152 + ssid->domainid = subj->domain_id; 18.153 + ssid->primary_ssid = NULL; 18.154 + ssid->secondary_ssid = NULL; 18.155 + 18.156 + if (ACM_USE_SECURITY_POLICY != ACM_NULL_POLICY) 18.157 + ssid->ssidref = ssidref; 18.158 + else 18.159 + ssid->ssidref = ACM_DEFAULT_SSID; 18.160 + 18.161 + subj->ssid = ssid; 18.162 + /* now fill in primary and secondary parts; we only get here through hooks */ 18.163 + if (acm_primary_ops->init_domain_ssid != NULL) 18.164 + ret1 = acm_primary_ops->init_domain_ssid(&(ssid->primary_ssid), ssidref); 18.165 + else 18.166 + ret1 = ACM_OK; 18.167 + 18.168 + if (acm_secondary_ops->init_domain_ssid != NULL) 18.169 + ret2 = acm_secondary_ops->init_domain_ssid(&(ssid->secondary_ssid), ssidref); 18.170 + else 18.171 + ret2 = ACM_OK; 18.172 + 18.173 + if ((ret1 != ACM_OK) || (ret2 != ACM_OK)) { 18.174 + printk("%s: ERROR instantiating individual ssids for domain 0x%02x.\n", 18.175 + __func__, subj->domain_id); 18.176 + acm_free_domain_ssid(ssid); 18.177 + put_domain(subj); 18.178 + return ACM_INIT_SSID_ERROR; 18.179 + } 18.180 + printk("%s: assigned domain %x the ssidref=%x.\n", __func__, id, ssid->ssidref); 18.181 + put_domain(subj); 18.182 + return ACM_OK; 18.183 +} 18.184 + 18.185 + 18.186 +int 18.187 +acm_free_domain_ssid(struct acm_ssid_domain *ssid) 18.188 +{ 18.189 + domid_t id; 18.190 + 18.191 + /* domain is already gone, just ssid is left */ 18.192 + if (ssid == NULL) { 18.193 + printk("%s: ACM_NULL_POINTER ERROR.\n", __func__); 18.194 + return ACM_NULL_POINTER_ERROR; 18.195 + } 18.196 + id = ssid->domainid; 18.197 + ssid->subject = NULL; 18.198 + 18.199 + if (acm_primary_ops->free_domain_ssid != NULL) /* null policy */ 18.200 + acm_primary_ops->free_domain_ssid(ssid->primary_ssid); 18.201 + ssid->primary_ssid = NULL; 18.202 + if (acm_secondary_ops->free_domain_ssid != NULL) 18.203 + acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid); 18.204 + ssid->secondary_ssid = NULL; 18.205 + xfree(ssid); 18.206 + printkd("%s: Freed individual domain ssid (domain=%02x).\n",__func__, id); 18.207 + return ACM_OK; 18.208 +}
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/xen/acm/acm_null_hooks.c Mon Jun 20 22:28:08 2005 +0000 19.3 @@ -0,0 +1,76 @@ 19.4 +/**************************************************************** 19.5 + * acm_null_hooks.c 19.6 + * 19.7 + * Copyright (C) 2005 IBM Corporation 19.8 + * 19.9 + * Author: 19.10 + * Reiner Sailer <sailer@watson.ibm.com> 19.11 + * 19.12 + * This program is free software; you can redistribute it and/or 19.13 + * modify it under the terms of the GNU General Public License as 19.14 + * published by the Free Software Foundation, version 2 of the 19.15 + * License. 19.16 + */ 19.17 +#include <acm/acm_hooks.h> 19.18 + 19.19 +static int 19.20 +null_init_domain_ssid(void **chwall_ssid, ssidref_t ssidref) 19.21 +{ 19.22 + return ACM_OK; 19.23 +} 19.24 + 19.25 + 19.26 +static void 19.27 +null_free_domain_ssid(void *chwall_ssid) 19.28 +{ 19.29 + return; 19.30 +} 19.31 + 19.32 + 19.33 +static int 19.34 +null_dump_binary_policy(u8 *buf, u16 buf_size) 19.35 +{ 19.36 + return 0; 19.37 +} 19.38 + 19.39 + 19.40 + 19.41 +static int 19.42 +null_set_binary_policy(u8 *buf, u16 buf_size) 19.43 +{ 19.44 + return -1; 19.45 +} 19.46 + 19.47 + 19.48 +static int 19.49 +null_dump_stats(u8 *buf, u16 buf_size) 19.50 +{ 19.51 + /* no stats for NULL policy */ 19.52 + return 0; 19.53 +} 19.54 + 19.55 + 19.56 +/* now define the hook structure similarly to LSM */ 19.57 +struct acm_operations acm_null_ops = { 19.58 + .init_domain_ssid = null_init_domain_ssid, 19.59 + .free_domain_ssid = null_free_domain_ssid, 19.60 + .dump_binary_policy = null_dump_binary_policy, 19.61 + .set_binary_policy = null_set_binary_policy, 19.62 + .dump_statistics = null_dump_stats, 19.63 + /* domain management control hooks */ 19.64 + .pre_domain_create = NULL, 19.65 + .post_domain_create = NULL, 19.66 + .fail_domain_create = NULL, 19.67 + .post_domain_destroy = NULL, 19.68 + /* event channel control hooks */ 19.69 + .pre_eventchannel_unbound = NULL, 19.70 + .fail_eventchannel_unbound = NULL, 19.71 + .pre_eventchannel_interdomain = NULL, 19.72 + .fail_eventchannel_interdomain = NULL, 19.73 + /* grant table control hooks */ 19.74 + .pre_grant_map_ref = NULL, 19.75 + .fail_grant_map_ref = NULL, 19.76 + .pre_grant_setup = NULL, 19.77 + .fail_grant_setup = NULL 19.78 + 19.79 +};
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/xen/acm/acm_policy.c Mon Jun 20 22:28:08 2005 +0000 20.3 @@ -0,0 +1,197 @@ 20.4 +/**************************************************************** 20.5 + * acm_policy.c 20.6 + * 20.7 + * Copyright (C) 2005 IBM Corporation 20.8 + * 20.9 + * Author: 20.10 + * Reiner Sailer <sailer@watson.ibm.com> 20.11 + * 20.12 + * Contributions: 20.13 + * Stefan Berger <stefanb@watson.ibm.com> 20.14 + * support for network-byte-order binary policies 20.15 + * 20.16 + * This program is free software; you can redistribute it and/or 20.17 + * modify it under the terms of the GNU General Public License as 20.18 + * published by the Free Software Foundation, version 2 of the 20.19 + * License. 20.20 + * 20.21 + * sHype access control policy management for Xen. 20.22 + * This interface allows policy tools in authorized 20.23 + * domains to interact with the Xen access control module 20.24 + * 20.25 + */ 20.26 + 20.27 +#include <xen/config.h> 20.28 +#include <xen/errno.h> 20.29 +#include <xen/types.h> 20.30 +#include <xen/lib.h> 20.31 +#include <xen/delay.h> 20.32 +#include <xen/sched.h> 20.33 +#include <public/policy_ops.h> 20.34 +#include <acm/acm_core.h> 20.35 +#include <acm/acm_hooks.h> 20.36 +#include <acm/acm_endian.h> 20.37 + 20.38 +int 20.39 +acm_set_policy(void *buf, u16 buf_size, u16 policy) 20.40 +{ 20.41 + u8 *policy_buffer = NULL; 20.42 + struct acm_policy_buffer *pol; 20.43 + 20.44 + if (policy != ACM_USE_SECURITY_POLICY) { 20.45 + printk("%s: Loading incompatible policy (running: %s).\n", __func__, 20.46 + ACM_POLICY_NAME(ACM_USE_SECURITY_POLICY)); 20.47 + return -EFAULT; 20.48 + } 20.49 + /* now check correct buffer sizes for policy combinations */ 20.50 + if (policy == ACM_NULL_POLICY) { 20.51 + printkd("%s: NULL Policy, no policy needed.\n", __func__); 20.52 + goto out; 20.53 + } 20.54 + if (buf_size < sizeof(struct acm_policy_buffer)) 20.55 + return -EFAULT; 20.56 + /* 1. copy buffer from domain */ 20.57 + if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL) 20.58 + goto error_free; 20.59 + if (copy_from_user(policy_buffer, buf, buf_size)) { 20.60 + printk("%s: Error copying!\n",__func__); 20.61 + goto error_free; 20.62 + } 20.63 + /* 2. some sanity checking */ 20.64 + pol = (struct acm_policy_buffer *)policy_buffer; 20.65 + 20.66 + if ((ntohl(pol->magic) != ACM_MAGIC) || 20.67 + (ntohs(pol->primary_policy_code) != acm_bin_pol.primary_policy_code) || 20.68 + (ntohs(pol->secondary_policy_code) != acm_bin_pol.secondary_policy_code)) { 20.69 + printkd("%s: Wrong policy magics!\n", __func__); 20.70 + goto error_free; 20.71 + } 20.72 + if (buf_size != ntohl(pol->len)) { 20.73 + printk("%s: ERROR in buf size.\n", __func__); 20.74 + goto error_free; 20.75 + } 20.76 + 20.77 + /* get bin_policy lock and rewrite policy (release old one) */ 20.78 + write_lock(&acm_bin_pol_rwlock); 20.79 + 20.80 + /* 3. now get/set primary policy data */ 20.81 + if (acm_primary_ops->set_binary_policy(buf + ntohs(pol->primary_buffer_offset), 20.82 + ntohs(pol->secondary_buffer_offset) - 20.83 + ntohs(pol->primary_buffer_offset))) { 20.84 + goto error_lock_free; 20.85 + } 20.86 + /* 4. now get/set secondary policy data */ 20.87 + if (acm_secondary_ops->set_binary_policy(buf + ntohs(pol->secondary_buffer_offset), 20.88 + ntohl(pol->len) - 20.89 + ntohs(pol->secondary_buffer_offset))) { 20.90 + goto error_lock_free; 20.91 + } 20.92 + write_unlock(&acm_bin_pol_rwlock); 20.93 + out: 20.94 + printk("%s: Done .\n", __func__); 20.95 + if (policy_buffer != NULL) 20.96 + xfree(policy_buffer); 20.97 + return ACM_OK; 20.98 + 20.99 + error_lock_free: 20.100 + write_unlock(&acm_bin_pol_rwlock); 20.101 + error_free: 20.102 + printk("%s: Error setting policy.\n", __func__); 20.103 + if (policy_buffer != NULL) 20.104 + xfree(policy_buffer); 20.105 + return -ENOMEM; 20.106 +} 20.107 + 20.108 +int 20.109 +acm_get_policy(void *buf, u16 buf_size) 20.110 +{ 20.111 + u8 *policy_buffer; 20.112 + int ret; 20.113 + struct acm_policy_buffer *bin_pol; 20.114 + 20.115 + if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL) 20.116 + return -ENOMEM; 20.117 + 20.118 + read_lock(&acm_bin_pol_rwlock); 20.119 + /* future: read policy from file and set it */ 20.120 + bin_pol = (struct acm_policy_buffer *)policy_buffer; 20.121 + bin_pol->magic = htonl(ACM_MAGIC); 20.122 + bin_pol->policyversion = htonl(POLICY_INTERFACE_VERSION); 20.123 + bin_pol->primary_policy_code = htons(acm_bin_pol.primary_policy_code); 20.124 + bin_pol->secondary_policy_code = htons(acm_bin_pol.secondary_policy_code); 20.125 + 20.126 + bin_pol->len = htonl(sizeof(struct acm_policy_buffer)); 20.127 + bin_pol->primary_buffer_offset = htons(ntohl(bin_pol->len)); 20.128 + bin_pol->secondary_buffer_offset = htons(ntohl(bin_pol->len)); 20.129 + 20.130 + ret = acm_primary_ops->dump_binary_policy (policy_buffer + ntohs(bin_pol->primary_buffer_offset), 20.131 + buf_size - ntohs(bin_pol->primary_buffer_offset)); 20.132 + if (ret < 0) { 20.133 + printk("%s: ERROR creating chwallpolicy buffer.\n", __func__); 20.134 + read_unlock(&acm_bin_pol_rwlock); 20.135 + return -1; 20.136 + } 20.137 + bin_pol->len = htonl(ntohl(bin_pol->len) + ret); 20.138 + bin_pol->secondary_buffer_offset = htons(ntohl(bin_pol->len)); 20.139 + 20.140 + ret = acm_secondary_ops->dump_binary_policy(policy_buffer + ntohs(bin_pol->secondary_buffer_offset), 20.141 + buf_size - ntohs(bin_pol->secondary_buffer_offset)); 20.142 + if (ret < 0) { 20.143 + printk("%s: ERROR creating chwallpolicy buffer.\n", __func__); 20.144 + read_unlock(&acm_bin_pol_rwlock); 20.145 + return -1; 20.146 + } 20.147 + bin_pol->len = htonl(ntohl(bin_pol->len) + ret); 20.148 + read_unlock(&acm_bin_pol_rwlock); 20.149 + if (copy_to_user(buf, policy_buffer, ntohl(bin_pol->len))) 20.150 + return -EFAULT; 20.151 + xfree(policy_buffer); 20.152 + return ACM_OK; 20.153 +} 20.154 + 20.155 +int 20.156 +acm_dump_statistics(void *buf, u16 buf_size) 20.157 +{ 20.158 + /* send stats to user space */ 20.159 + u8 *stats_buffer; 20.160 + int len1, len2; 20.161 + struct acm_stats_buffer acm_stats; 20.162 + 20.163 + if ((stats_buffer = xmalloc_array(u8, buf_size)) == NULL) 20.164 + return -ENOMEM; 20.165 + 20.166 + read_lock(&acm_bin_pol_rwlock); 20.167 + 20.168 + len1 = acm_primary_ops->dump_statistics(stats_buffer + sizeof(struct acm_stats_buffer), 20.169 + buf_size - sizeof(struct acm_stats_buffer)); 20.170 + if (len1 < 0) 20.171 + goto error_lock_free; 20.172 + 20.173 + len2 = acm_secondary_ops->dump_statistics(stats_buffer + sizeof(struct acm_stats_buffer) + len1, 20.174 + buf_size - sizeof(struct acm_stats_buffer) - len1); 20.175 + if (len2 < 0) 20.176 + goto error_lock_free; 20.177 + 20.178 + acm_stats.magic = htonl(ACM_MAGIC); 20.179 + acm_stats.policyversion = htonl(POLICY_INTERFACE_VERSION); 20.180 + acm_stats.primary_policy_code = htons(acm_bin_pol.primary_policy_code); 20.181 + acm_stats.secondary_policy_code = htons(acm_bin_pol.secondary_policy_code); 20.182 + acm_stats.primary_stats_offset = htons(sizeof(struct acm_stats_buffer)); 20.183 + acm_stats.secondary_stats_offset = htons(sizeof(struct acm_stats_buffer) + len1); 20.184 + acm_stats.len = htonl(sizeof(struct acm_stats_buffer) + len1 + len2); 20.185 + memcpy(stats_buffer, &acm_stats, sizeof(struct acm_stats_buffer)); 20.186 + 20.187 + if (copy_to_user(buf, stats_buffer, sizeof(struct acm_stats_buffer) + len1 + len2)) 20.188 + goto error_lock_free; 20.189 + 20.190 + read_unlock(&acm_bin_pol_rwlock); 20.191 + xfree(stats_buffer); 20.192 + return ACM_OK; 20.193 + 20.194 + error_lock_free: 20.195 + read_unlock(&acm_bin_pol_rwlock); 20.196 + xfree(stats_buffer); 20.197 + return -EFAULT; 20.198 +} 20.199 + 20.200 +/*eof*/
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/xen/acm/acm_simple_type_enforcement_hooks.c Mon Jun 20 22:28:08 2005 +0000 21.3 @@ -0,0 +1,638 @@ 21.4 +/**************************************************************** 21.5 + * acm_simple_type_enforcement_hooks.c 21.6 + * 21.7 + * Copyright (C) 2005 IBM Corporation 21.8 + * 21.9 + * Author: 21.10 + * Reiner Sailer <sailer@watson.ibm.com> 21.11 + * 21.12 + * Contributors: 21.13 + * Stefan Berger <stefanb@watson.ibm.com> 21.14 + * support for network order binary policies 21.15 + * 21.16 + * This program is free software; you can redistribute it and/or 21.17 + * modify it under the terms of the GNU General Public License as 21.18 + * published by the Free Software Foundation, version 2 of the 21.19 + * License. 21.20 + * 21.21 + * sHype Simple Type Enforcement for Xen 21.22 + * STE allows to control which domains can setup sharing 21.23 + * (eventchannels right now) with which other domains. Hooks 21.24 + * are defined and called throughout Xen when domains bind to 21.25 + * shared resources (setup eventchannels) and a domain is allowed 21.26 + * to setup sharing with another domain if and only if both domains 21.27 + * share at least on common type. 21.28 + * 21.29 + */ 21.30 +#include <xen/lib.h> 21.31 +#include <asm/types.h> 21.32 +#include <asm/current.h> 21.33 +#include <acm/acm_hooks.h> 21.34 +#include <asm/atomic.h> 21.35 +#include <acm/acm_endian.h> 21.36 + 21.37 +/* local cache structures for chinese wall policy */ 21.38 +struct ste_binary_policy ste_bin_pol; 21.39 + 21.40 +static inline int have_common_type (ssidref_t ref1, ssidref_t ref2) { 21.41 + int i; 21.42 + for(i=0; i< ste_bin_pol.max_types; i++) 21.43 + if ( ste_bin_pol.ssidrefs[ref1*ste_bin_pol.max_types + i] && 21.44 + ste_bin_pol.ssidrefs[ref2*ste_bin_pol.max_types + i]) { 21.45 + printkd("%s: common type #%02x.\n", __func__, i); 21.46 + return 1; 21.47 + } 21.48 + return 0; 21.49 +} 21.50 + 21.51 +/* Helper function: return = (subj and obj share a common type) */ 21.52 +static int share_common_type(struct domain *subj, struct domain *obj) 21.53 +{ 21.54 + ssidref_t ref_s, ref_o; 21.55 + int ret; 21.56 + 21.57 + if ((subj == NULL) || (obj == NULL) || (subj->ssid == NULL) || (obj->ssid == NULL)) 21.58 + return 0; 21.59 + read_lock(&acm_bin_pol_rwlock); 21.60 + /* lookup the policy-local ssids */ 21.61 + ref_s = ((struct ste_ssid *)(GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 21.62 + (struct acm_ssid_domain *)subj->ssid)))->ste_ssidref; 21.63 + ref_o = ((struct ste_ssid *)(GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 21.64 + (struct acm_ssid_domain *)obj->ssid)))->ste_ssidref; 21.65 + /* check whether subj and obj share a common ste type */ 21.66 + ret = have_common_type(ref_s, ref_o); 21.67 + read_unlock(&acm_bin_pol_rwlock); 21.68 + return ret; 21.69 +} 21.70 + 21.71 +/* 21.72 + * Initializing chinese wall policy (will be filled by policy partition 21.73 + * using setpolicy command) 21.74 + */ 21.75 +int acm_init_ste_policy(void) 21.76 +{ 21.77 + /* minimal startup policy; policy write-locked already */ 21.78 + ste_bin_pol.max_types = 1; 21.79 + ste_bin_pol.max_ssidrefs = 1; 21.80 + ste_bin_pol.ssidrefs = (domaintype_t *)xmalloc_array(domaintype_t, 1); 21.81 + 21.82 + if (ste_bin_pol.ssidrefs == NULL) 21.83 + return ACM_INIT_SSID_ERROR; 21.84 + 21.85 + /* initialize state */ 21.86 + ste_bin_pol.ssidrefs[0] = 1; 21.87 + 21.88 + /* init stats */ 21.89 + atomic_set(&(ste_bin_pol.ec_eval_count), 0); 21.90 + atomic_set(&(ste_bin_pol.ec_denied_count), 0); 21.91 + atomic_set(&(ste_bin_pol.ec_cachehit_count), 0); 21.92 + atomic_set(&(ste_bin_pol.gt_eval_count), 0); 21.93 + atomic_set(&(ste_bin_pol.gt_denied_count), 0); 21.94 + atomic_set(&(ste_bin_pol.gt_cachehit_count), 0); 21.95 + return ACM_OK; 21.96 +} 21.97 + 21.98 + 21.99 +/* ste initialization function hooks */ 21.100 +static int 21.101 +ste_init_domain_ssid(void **ste_ssid, ssidref_t ssidref) 21.102 +{ 21.103 + int i; 21.104 + struct ste_ssid *ste_ssidp = xmalloc(struct ste_ssid); 21.105 + traceprintk("%s.\n", __func__); 21.106 + 21.107 + if (ste_ssidp == NULL) 21.108 + return ACM_INIT_SSID_ERROR; 21.109 + 21.110 + /* get policy-local ssid reference */ 21.111 + ste_ssidp->ste_ssidref = GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref); 21.112 + if (ste_ssidp->ste_ssidref >= ste_bin_pol.max_ssidrefs) { 21.113 + printkd("%s: ERROR ste_ssidref (%x) > max(%x).\n", 21.114 + __func__, ste_ssidp->ste_ssidref, ste_bin_pol.max_ssidrefs-1); 21.115 + xfree(ste_ssidp); 21.116 + return ACM_INIT_SSID_ERROR; 21.117 + } 21.118 + /* clean ste cache */ 21.119 + for (i=0; i<ACM_TE_CACHE_SIZE; i++) 21.120 + ste_ssidp->ste_cache[i].valid = FREE; 21.121 + 21.122 + (*ste_ssid) = ste_ssidp; 21.123 + printkd("%s: determined ste_ssidref to %x.\n", 21.124 + __func__, ste_ssidp->ste_ssidref); 21.125 + return ACM_OK; 21.126 +} 21.127 + 21.128 + 21.129 +static void 21.130 +ste_free_domain_ssid(void *ste_ssid) 21.131 +{ 21.132 + traceprintk("%s.\n", __func__); 21.133 + if (ste_ssid != NULL) 21.134 + xfree(ste_ssid); 21.135 + return; 21.136 +} 21.137 + 21.138 +/* dump type enforcement cache; policy read-locked already */ 21.139 +static int 21.140 +ste_dump_policy(u8 *buf, u16 buf_size) { 21.141 + struct acm_ste_policy_buffer *ste_buf = (struct acm_ste_policy_buffer *)buf; 21.142 + int ret = 0; 21.143 + 21.144 + ste_buf->ste_max_types = htons(ste_bin_pol.max_types); 21.145 + ste_buf->ste_max_ssidrefs = htons(ste_bin_pol.max_ssidrefs); 21.146 + ste_buf->policy_code = htons(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY); 21.147 + ste_buf->ste_ssid_offset = htons(sizeof(struct acm_ste_policy_buffer)); 21.148 + ret = ntohs(ste_buf->ste_ssid_offset) + 21.149 + sizeof(domaintype_t)*ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types; 21.150 + 21.151 + /* now copy buffer over */ 21.152 + arrcpy(buf + ntohs(ste_buf->ste_ssid_offset), 21.153 + ste_bin_pol.ssidrefs, 21.154 + sizeof(domaintype_t), 21.155 + ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types); 21.156 + 21.157 + return ret; 21.158 +} 21.159 + 21.160 +/* ste_init_state is called when a policy is changed to detect violations (return != 0). 21.161 + * from a security point of view, we simulate that all running domains are re-started and 21.162 + * all sharing decisions are replayed to detect violations or current sharing behavior 21.163 + * (right now: event_channels, future: also grant_tables) 21.164 + */ 21.165 +static int 21.166 +ste_init_state(struct acm_ste_policy_buffer *ste_buf, domaintype_t *ssidrefs) 21.167 +{ 21.168 + int violation = 1; 21.169 + struct ste_ssid *ste_ssid, *ste_rssid; 21.170 + ssidref_t ste_ssidref, ste_rssidref; 21.171 + struct domain **pd, *rdom; 21.172 + domid_t rdomid; 21.173 + grant_entry_t sha_copy; 21.174 + int port, i; 21.175 + 21.176 + read_lock(&domlist_lock); /* go by domain? or directly by global? event/grant list */ 21.177 + /* go through all domains and adjust policy as if this domain was started now */ 21.178 + pd = &domain_list; 21.179 + for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) { 21.180 + ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 21.181 + (struct acm_ssid_domain *)(*pd)->ssid); 21.182 + ste_ssidref = ste_ssid->ste_ssidref; 21.183 + traceprintk("%s: validating policy for eventch domain %x (ste-Ref=%x).\n", 21.184 + __func__, (*pd)->domain_id, ste_ssidref); 21.185 + /* a) check for event channel conflicts */ 21.186 + for (port=0; port < NR_EVTCHN_BUCKETS; port++) { 21.187 + spin_lock(&(*pd)->evtchn_lock); 21.188 + if ((*pd)->evtchn[port] == NULL) { 21.189 + spin_unlock(&(*pd)->evtchn_lock); 21.190 + continue; 21.191 + } 21.192 + if ((*pd)->evtchn[port]->state == ECS_INTERDOMAIN) { 21.193 + rdom = (*pd)->evtchn[port]->u.interdomain.remote_dom; 21.194 + rdomid = rdom->domain_id; 21.195 + /* rdom now has remote domain */ 21.196 + ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 21.197 + (struct acm_ssid_domain *)(rdom->ssid)); 21.198 + ste_rssidref = ste_rssid->ste_ssidref; 21.199 + } else if ((*pd)->evtchn[port]->state == ECS_UNBOUND) { 21.200 + rdomid = (*pd)->evtchn[port]->u.unbound.remote_domid; 21.201 + if ((rdom = find_domain_by_id(rdomid)) == NULL) { 21.202 + printk("%s: Error finding domain to id %x!\n", __func__, rdomid); 21.203 + goto out; 21.204 + } 21.205 + /* rdom now has remote domain */ 21.206 + ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 21.207 + (struct acm_ssid_domain *)(rdom->ssid)); 21.208 + ste_rssidref = ste_rssid->ste_ssidref; 21.209 + put_domain(rdom); 21.210 + } else { 21.211 + spin_unlock(&(*pd)->evtchn_lock); 21.212 + continue; /* port unused */ 21.213 + } 21.214 + spin_unlock(&(*pd)->evtchn_lock); 21.215 + 21.216 + /* rdom now has remote domain */ 21.217 + ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 21.218 + (struct acm_ssid_domain *)(rdom->ssid)); 21.219 + ste_rssidref = ste_rssid->ste_ssidref; 21.220 + traceprintk("%s: eventch: domain %x (ssidref %x) --> domain %x (rssidref %x) used (port %x).\n", 21.221 + __func__, (*pd)->domain_id, ste_ssidref, rdom->domain_id, ste_rssidref, port); 21.222 + /* check whether on subj->ssid, obj->ssid share a common type*/ 21.223 + if (!have_common_type(ste_ssidref, ste_rssidref)) { 21.224 + printkd("%s: Policy violation in event channel domain %x -> domain %x.\n", 21.225 + __func__, (*pd)->domain_id, rdomid); 21.226 + goto out; 21.227 + } 21.228 + } 21.229 + /* b) check for grant table conflicts on shared pages */ 21.230 + if ((*pd)->grant_table->shared == NULL) { 21.231 + printkd("%s: Grant ... sharing for domain %x not setup!\n", __func__, (*pd)->domain_id); 21.232 + continue; 21.233 + } 21.234 + for ( i = 0; i < NR_GRANT_ENTRIES; i++ ) { 21.235 + sha_copy = (*pd)->grant_table->shared[i]; 21.236 + if ( sha_copy.flags ) { 21.237 + printkd("%s: grant dom (%hu) SHARED (%d) flags:(%hx) dom:(%hu) frame:(%lx)\n", 21.238 + __func__, (*pd)->domain_id, i, sha_copy.flags, sha_copy.domid, 21.239 + (unsigned long)sha_copy.frame); 21.240 + rdomid = sha_copy.domid; 21.241 + if ((rdom = find_domain_by_id(rdomid)) == NULL) { 21.242 + printkd("%s: domain not found ERROR!\n", __func__); 21.243 + goto out; 21.244 + }; 21.245 + /* rdom now has remote domain */ 21.246 + ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 21.247 + (struct acm_ssid_domain *)(rdom->ssid)); 21.248 + ste_rssidref = ste_rssid->ste_ssidref; 21.249 + put_domain(rdom); 21.250 + if (!have_common_type(ste_ssidref, ste_rssidref)) { 21.251 + printkd("%s: Policy violation in grant table sharing domain %x -> domain %x.\n", 21.252 + __func__, (*pd)->domain_id, rdomid); 21.253 + goto out; 21.254 + } 21.255 + } 21.256 + } 21.257 + } 21.258 + violation = 0; 21.259 + out: 21.260 + read_unlock(&domlist_lock); 21.261 + return violation; 21.262 + /* returning "violation != 0" means that existing sharing between domains would not 21.263 + * have been allowed if the new policy had been enforced before the sharing; for ste, 21.264 + * this means that there are at least 2 domains that have established sharing through 21.265 + * event-channels or grant-tables but these two domains don't have no longer a common 21.266 + * type in their typesets referenced by their ssidrefs */ 21.267 +} 21.268 + 21.269 +/* set new policy; policy write-locked already */ 21.270 +static int 21.271 +ste_set_policy(u8 *buf, u16 buf_size) 21.272 +{ 21.273 + struct acm_ste_policy_buffer *ste_buf = (struct acm_ste_policy_buffer *)buf; 21.274 + void *ssidrefsbuf; 21.275 + struct ste_ssid *ste_ssid; 21.276 + struct domain **pd; 21.277 + int i; 21.278 + 21.279 + /* Convert endianess of policy */ 21.280 + ste_buf->policy_code = ntohs(ste_buf->policy_code); 21.281 + ste_buf->ste_max_types = ntohs(ste_buf->ste_max_types); 21.282 + ste_buf->ste_max_ssidrefs = ntohs(ste_buf->ste_max_ssidrefs); 21.283 + ste_buf->ste_ssid_offset = ntohs(ste_buf->ste_ssid_offset); 21.284 + 21.285 + /* 1. create and copy-in new ssidrefs buffer */ 21.286 + ssidrefsbuf = xmalloc_array(u8, sizeof(domaintype_t)*ste_buf->ste_max_types*ste_buf->ste_max_ssidrefs); 21.287 + if (ssidrefsbuf == NULL) { 21.288 + return -ENOMEM; 21.289 + } 21.290 + if (ste_buf->ste_ssid_offset + sizeof(domaintype_t) * ste_buf->ste_max_ssidrefs*ste_buf->ste_max_types > buf_size) 21.291 + goto error_free; 21.292 + 21.293 + arrcpy(ssidrefsbuf, 21.294 + buf + ste_buf->ste_ssid_offset, 21.295 + sizeof(domaintype_t), 21.296 + ste_buf->ste_max_ssidrefs*ste_buf->ste_max_types); 21.297 + 21.298 + /* 2. now re-calculate sharing decisions based on running domains; 21.299 + * this can fail if new policy is conflicting with sharing of running domains 21.300 + * now: reject violating new policy; future: adjust sharing through revoking sharing */ 21.301 + if (ste_init_state(ste_buf, (domaintype_t *)ssidrefsbuf)) { 21.302 + printk("%s: New policy conflicts with running domains. Policy load aborted.\n", __func__); 21.303 + goto error_free; /* new policy conflicts with sharing of running domains */ 21.304 + } 21.305 + /* 3. replace old policy (activate new policy) */ 21.306 + ste_bin_pol.max_types = ste_buf->ste_max_types; 21.307 + ste_bin_pol.max_ssidrefs = ste_buf->ste_max_ssidrefs; 21.308 + if (ste_bin_pol.ssidrefs) 21.309 + xfree(ste_bin_pol.ssidrefs); 21.310 + ste_bin_pol.ssidrefs = (domaintype_t *)ssidrefsbuf; 21.311 + 21.312 + /* clear all ste caches */ 21.313 + read_lock(&domlist_lock); 21.314 + pd = &domain_list; 21.315 + for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) { 21.316 + ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 21.317 + (struct acm_ssid_domain *)(*pd)->ssid); 21.318 + for (i=0; i<ACM_TE_CACHE_SIZE; i++) 21.319 + ste_ssid->ste_cache[i].valid = FREE; 21.320 + } 21.321 + read_unlock(&domlist_lock); 21.322 + return ACM_OK; 21.323 + 21.324 +error_free: 21.325 + printk("%s: ERROR setting policy.\n", __func__); 21.326 + if (ssidrefsbuf != NULL) xfree(ssidrefsbuf); 21.327 + return -EFAULT; 21.328 +} 21.329 + 21.330 +static int 21.331 +ste_dump_stats(u8 *buf, u16 buf_len) 21.332 +{ 21.333 + struct acm_ste_stats_buffer stats; 21.334 + 21.335 +#ifdef ACM_DEBUG 21.336 + int i; 21.337 + struct ste_ssid *ste_ssid; 21.338 + struct domain **pd; 21.339 + 21.340 + printk("ste: Decision caches:\n"); 21.341 + /* go through all domains and adjust policy as if this domain was started now */ 21.342 + read_lock(&domlist_lock); /* go by domain? or directly by global? event/grant list */ 21.343 + pd = &domain_list; 21.344 + for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) { 21.345 + printk("ste: Cache Domain %02x.\n", (*pd)->domain_id); 21.346 + ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 21.347 + (struct acm_ssid_domain *)(*pd)->ssid); 21.348 + for (i=0; i<ACM_TE_CACHE_SIZE; i++) 21.349 + printk("\t\tcache[%02x] = %s, domid=%x.\n", i, 21.350 + (ste_ssid->ste_cache[i].valid == VALID) ? 21.351 + "VALID" : "FREE", 21.352 + (ste_ssid->ste_cache[i].valid == VALID) ? 21.353 + ste_ssid->ste_cache[i].id : 0xffffffff); 21.354 + } 21.355 + read_unlock(&domlist_lock); 21.356 + /* init stats */ 21.357 + printk("STE-Policy Security Hook Statistics:\n"); 21.358 + printk("ste: event_channel eval_count = %x\n", atomic_read(&(ste_bin_pol.ec_eval_count))); 21.359 + printk("ste: event_channel denied_count = %x\n", atomic_read(&(ste_bin_pol.ec_denied_count))); 21.360 + printk("ste: event_channel cache_hit_count = %x\n", atomic_read(&(ste_bin_pol.ec_cachehit_count))); 21.361 + printk("ste:\n"); 21.362 + printk("ste: grant_table eval_count = %x\n", atomic_read(&(ste_bin_pol.gt_eval_count))); 21.363 + printk("ste: grant_table denied_count = %x\n", atomic_read(&(ste_bin_pol.gt_denied_count))); 21.364 + printk("ste: grant_table cache_hit_count = %x\n", atomic_read(&(ste_bin_pol.gt_cachehit_count))); 21.365 +#endif 21.366 + 21.367 + if (buf_len < sizeof(struct acm_ste_stats_buffer)) 21.368 + return -ENOMEM; 21.369 + 21.370 + /* now send the hook counts to user space */ 21.371 + stats.ec_eval_count = htonl(atomic_read(&ste_bin_pol.ec_eval_count)); 21.372 + stats.gt_eval_count = htonl(atomic_read(&ste_bin_pol.gt_eval_count)); 21.373 + stats.ec_denied_count = htonl(atomic_read(&ste_bin_pol.ec_denied_count)); 21.374 + stats.gt_denied_count = htonl(atomic_read(&ste_bin_pol.gt_denied_count)); 21.375 + stats.ec_cachehit_count = htonl(atomic_read(&ste_bin_pol.ec_cachehit_count)); 21.376 + stats.gt_cachehit_count = htonl(atomic_read(&ste_bin_pol.gt_cachehit_count)); 21.377 + memcpy(buf, &stats, sizeof(struct acm_ste_stats_buffer)); 21.378 + return sizeof(struct acm_ste_stats_buffer); 21.379 +} 21.380 + 21.381 + 21.382 +/* we need to go through this before calling the hooks, 21.383 + * returns 1 == cache hit */ 21.384 +static int inline 21.385 +check_cache(struct domain *dom, domid_t rdom) { 21.386 + struct ste_ssid *ste_ssid; 21.387 + int i; 21.388 + 21.389 + printkd("checking cache: %x --> %x.\n", dom->domain_id, rdom); 21.390 + ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 21.391 + (struct acm_ssid_domain *)(dom)->ssid); 21.392 + 21.393 + for(i=0; i< ACM_TE_CACHE_SIZE; i++) { 21.394 + if ((ste_ssid->ste_cache[i].valid == VALID) && 21.395 + (ste_ssid->ste_cache[i].id == rdom)) { 21.396 + printkd("cache hit (entry %x, id= %x!\n", i, ste_ssid->ste_cache[i].id); 21.397 + return 1; 21.398 + } 21.399 + } 21.400 + return 0; 21.401 +} 21.402 + 21.403 + 21.404 +/* we only get here if there is NO entry yet; no duplication check! */ 21.405 +static void inline 21.406 +cache_result(struct domain *subj, struct domain *obj) { 21.407 + struct ste_ssid *ste_ssid; 21.408 + int i; 21.409 + printkd("caching from doms: %x --> %x.\n", subj->domain_id, obj->domain_id); 21.410 + ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 21.411 + (struct acm_ssid_domain *)(subj)->ssid); 21.412 + for(i=0; i< ACM_TE_CACHE_SIZE; i++) 21.413 + if (ste_ssid->ste_cache[i].valid == FREE) 21.414 + break; 21.415 + if (i< ACM_TE_CACHE_SIZE) { 21.416 + ste_ssid->ste_cache[i].valid = VALID; 21.417 + ste_ssid->ste_cache[i].id = obj->domain_id; 21.418 + } else 21.419 + printk ("Cache of dom %x is full!\n", subj->domain_id); 21.420 +} 21.421 + 21.422 +/* deletes entries for domain 'id' from all caches (re-use) */ 21.423 +static void inline 21.424 +clean_id_from_cache(domid_t id) 21.425 +{ 21.426 + struct ste_ssid *ste_ssid; 21.427 + int i; 21.428 + struct domain **pd; 21.429 + 21.430 + printkd("deleting cache for dom %x.\n", id); 21.431 + 21.432 + read_lock(&domlist_lock); /* look through caches of all domains */ 21.433 + pd = &domain_list; 21.434 + for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) { 21.435 + ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, 21.436 + (struct acm_ssid_domain *)(*pd)->ssid); 21.437 + for (i=0; i<ACM_TE_CACHE_SIZE; i++) 21.438 + if ((ste_ssid->ste_cache[i].valid == VALID) && 21.439 + (ste_ssid->ste_cache[i].id = id)) 21.440 + ste_ssid->ste_cache[i].valid = FREE; 21.441 + } 21.442 + read_unlock(&domlist_lock); 21.443 +} 21.444 + 21.445 +/*************************** 21.446 + * Authorization functions 21.447 + **************************/ 21.448 + 21.449 +static int 21.450 +ste_pre_domain_create(void *subject_ssid, ssidref_t ssidref) 21.451 +{ 21.452 + /* check for ssidref in range for policy */ 21.453 + ssidref_t ste_ssidref; 21.454 + traceprintk("%s.\n", __func__); 21.455 + 21.456 + read_lock(&acm_bin_pol_rwlock); 21.457 + ste_ssidref = GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref); 21.458 + if (ste_ssidref == ACM_DEFAULT_LOCAL_SSID) { 21.459 + printk("%s: ERROR STE SSID is NOT SET but policy enforced.\n", __func__); 21.460 + read_unlock(&acm_bin_pol_rwlock); 21.461 + return ACM_ACCESS_DENIED; /* catching and indicating config error */ 21.462 + } 21.463 + if (ste_ssidref >= ste_bin_pol.max_ssidrefs) { 21.464 + printk("%s: ERROR ste_ssidref > max(%x).\n", 21.465 + __func__, ste_bin_pol.max_ssidrefs-1); 21.466 + read_unlock(&acm_bin_pol_rwlock); 21.467 + return ACM_ACCESS_DENIED; 21.468 + } 21.469 + read_unlock(&acm_bin_pol_rwlock); 21.470 + return ACM_ACCESS_PERMITTED; 21.471 +} 21.472 + 21.473 +static void 21.474 +ste_post_domain_destroy(void *subject_ssid, domid_t id) 21.475 +{ 21.476 + /* clean all cache entries for destroyed domain (might be re-used) */ 21.477 + clean_id_from_cache(id); 21.478 +} 21.479 + 21.480 +/* -------- EVENTCHANNEL OPERATIONS -----------*/ 21.481 +static int 21.482 +ste_pre_eventchannel_unbound(domid_t id) { 21.483 + struct domain *subj, *obj; 21.484 + int ret; 21.485 + traceprintk("%s: dom%x-->dom%x.\n", 21.486 + __func__, current->domain->domain_id, id); 21.487 + 21.488 + if (check_cache(current->domain, id)) { 21.489 + atomic_inc(&ste_bin_pol.ec_cachehit_count); 21.490 + return ACM_ACCESS_PERMITTED; 21.491 + } 21.492 + atomic_inc(&ste_bin_pol.ec_eval_count); 21.493 + subj = current->domain; 21.494 + obj = find_domain_by_id(id); 21.495 + 21.496 + if (share_common_type(subj, obj)) { 21.497 + cache_result(subj, obj); 21.498 + ret = ACM_ACCESS_PERMITTED; 21.499 + } else { 21.500 + atomic_inc(&ste_bin_pol.ec_denied_count); 21.501 + ret = ACM_ACCESS_DENIED; 21.502 + } 21.503 + if (obj != NULL) 21.504 + put_domain(obj); 21.505 + return ret; 21.506 +} 21.507 + 21.508 +static int 21.509 +ste_pre_eventchannel_interdomain(domid_t id1, domid_t id2) 21.510 +{ 21.511 + struct domain *subj, *obj; 21.512 + int ret; 21.513 + traceprintk("%s: dom%x-->dom%x.\n", __func__, 21.514 + (id1 == DOMID_SELF) ? current->domain->domain_id : id1, 21.515 + (id2 == DOMID_SELF) ? current->domain->domain_id : id2); 21.516 + 21.517 + /* following is a bit longer but ensures that we 21.518 + * "put" only domains that we where "find"-ing 21.519 + */ 21.520 + if (id1 == DOMID_SELF) id1 = current->domain->domain_id; 21.521 + if (id2 == DOMID_SELF) id2 = current->domain->domain_id; 21.522 + 21.523 + subj = find_domain_by_id(id1); 21.524 + obj = find_domain_by_id(id2); 21.525 + if ((subj == NULL) || (obj == NULL)) { 21.526 + ret = ACM_ACCESS_DENIED; 21.527 + goto out; 21.528 + } 21.529 + /* cache check late, but evtchn is not on performance critical path */ 21.530 + if (check_cache(subj, obj->domain_id)) { 21.531 + atomic_inc(&ste_bin_pol.ec_cachehit_count); 21.532 + ret = ACM_ACCESS_PERMITTED; 21.533 + goto out; 21.534 + } 21.535 + atomic_inc(&ste_bin_pol.ec_eval_count); 21.536 + 21.537 + if (share_common_type(subj, obj)) { 21.538 + cache_result(subj, obj); 21.539 + ret = ACM_ACCESS_PERMITTED; 21.540 + } else { 21.541 + atomic_inc(&ste_bin_pol.ec_denied_count); 21.542 + ret = ACM_ACCESS_DENIED; 21.543 + } 21.544 + out: 21.545 + if (obj != NULL) 21.546 + put_domain(obj); 21.547 + if (subj != NULL) 21.548 + put_domain(subj); 21.549 + return ret; 21.550 +} 21.551 + 21.552 +/* -------- SHARED MEMORY OPERATIONS -----------*/ 21.553 + 21.554 +static int 21.555 +ste_pre_grant_map_ref (domid_t id) { 21.556 + struct domain *obj, *subj; 21.557 + int ret; 21.558 + traceprintk("%s: dom%x-->dom%x.\n", __func__, 21.559 + current->domain->domain_id, id); 21.560 + 21.561 + if (check_cache(current->domain, id)) { 21.562 + atomic_inc(&ste_bin_pol.gt_cachehit_count); 21.563 + return ACM_ACCESS_PERMITTED; 21.564 + } 21.565 + atomic_inc(&ste_bin_pol.gt_eval_count); 21.566 + subj = current->domain; 21.567 + obj = find_domain_by_id(id); 21.568 + 21.569 + if (share_common_type(subj, obj)) { 21.570 + cache_result(subj, obj); 21.571 + ret = ACM_ACCESS_PERMITTED; 21.572 + } else { 21.573 + atomic_inc(&ste_bin_pol.gt_denied_count); 21.574 + printkd("%s: ACCESS DENIED!\n", __func__); 21.575 + ret = ACM_ACCESS_DENIED; 21.576 + } 21.577 + if (obj != NULL) 21.578 + put_domain(obj); 21.579 + return ret; 21.580 +} 21.581 + 21.582 +/* since setting up grant tables involves some implicit information 21.583 + flow from the creating domain to the domain that is setup, we 21.584 + check types in addition to the general authorization */ 21.585 +static int 21.586 +ste_pre_grant_setup (domid_t id) { 21.587 + struct domain *obj, *subj; 21.588 + int ret; 21.589 + traceprintk("%s: dom%x-->dom%x.\n", __func__, 21.590 + current->domain->domain_id, id); 21.591 + 21.592 + if (check_cache(current->domain, id)) { 21.593 + atomic_inc(&ste_bin_pol.gt_cachehit_count); 21.594 + return ACM_ACCESS_PERMITTED; 21.595 + } 21.596 + atomic_inc(&ste_bin_pol.gt_eval_count); 21.597 + /* a) check authorization (eventually use specific capabilities) */ 21.598 + if (!IS_PRIV(current->domain)) { 21.599 + printk("%s: Grant table management authorization denied ERROR!\n", __func__); 21.600 + return ACM_ACCESS_DENIED; 21.601 + } 21.602 + /* b) check types */ 21.603 + subj = current->domain; 21.604 + obj = find_domain_by_id(id); 21.605 + 21.606 + if (share_common_type(subj, obj)) { 21.607 + cache_result(subj, obj); 21.608 + ret = ACM_ACCESS_PERMITTED; 21.609 + } else { 21.610 + atomic_inc(&ste_bin_pol.gt_denied_count); 21.611 + ret = ACM_ACCESS_DENIED; 21.612 + } 21.613 + if (obj != NULL) 21.614 + put_domain(obj); 21.615 + return ret; 21.616 +} 21.617 + 21.618 +/* now define the hook structure similarly to LSM */ 21.619 +struct acm_operations acm_simple_type_enforcement_ops = { 21.620 + /* policy management services */ 21.621 + .init_domain_ssid = ste_init_domain_ssid, 21.622 + .free_domain_ssid = ste_free_domain_ssid, 21.623 + .dump_binary_policy = ste_dump_policy, 21.624 + .set_binary_policy = ste_set_policy, 21.625 + .dump_statistics = ste_dump_stats, 21.626 + /* domain management control hooks */ 21.627 + .pre_domain_create = ste_pre_domain_create, 21.628 + .post_domain_create = NULL, 21.629 + .fail_domain_create = NULL, 21.630 + .post_domain_destroy = ste_post_domain_destroy, 21.631 + /* event channel control hooks */ 21.632 + .pre_eventchannel_unbound = ste_pre_eventchannel_unbound, 21.633 + .fail_eventchannel_unbound = NULL, 21.634 + .pre_eventchannel_interdomain = ste_pre_eventchannel_interdomain, 21.635 + .fail_eventchannel_interdomain = NULL, 21.636 + /* grant table control hooks */ 21.637 + .pre_grant_map_ref = ste_pre_grant_map_ref, 21.638 + .fail_grant_map_ref = NULL, 21.639 + .pre_grant_setup = ste_pre_grant_setup, 21.640 + .fail_grant_setup = NULL, 21.641 +};
22.1 --- a/xen/arch/x86/setup.c Sun Jun 19 17:05:55 2005 +0000 22.2 +++ b/xen/arch/x86/setup.c Mon Jun 20 22:28:08 2005 +0000 22.3 @@ -20,6 +20,7 @@ 22.4 #include <asm/desc.h> 22.5 #include <asm/shadow.h> 22.6 #include <asm/e820.h> 22.7 +#include <public/acm_dom0_setup.h> 22.8 22.9 extern void dmi_scan_machine(void); 22.10 extern void generic_apic_probe(void); 22.11 @@ -393,12 +394,17 @@ void __init __start_xen(multiboot_info_t 22.12 22.13 shadow_mode_init(); 22.14 22.15 + /* initialize access control security module */ 22.16 + acm_init(); 22.17 + 22.18 /* Create initial domain 0. */ 22.19 dom0 = do_createdomain(0, 0); 22.20 if ( dom0 == NULL ) 22.21 panic("Error creating domain 0\n"); 22.22 22.23 set_bit(_DOMF_privileged, &dom0->domain_flags); 22.24 + /* post-create hooks sets security label */ 22.25 + acm_post_domain0_create(dom0->domain_id); 22.26 22.27 /* Grab the DOM0 command line. */ 22.28 cmdline = (char *)(mod[0].string ? __va(mod[0].string) : NULL);
23.1 --- a/xen/arch/x86/x86_32/entry.S Sun Jun 19 17:05:55 2005 +0000 23.2 +++ b/xen/arch/x86/x86_32/entry.S Mon Jun 20 22:28:08 2005 +0000 23.3 @@ -751,6 +751,7 @@ ENTRY(hypercall_table) 23.4 .long do_boot_vcpu 23.5 .long do_ni_hypercall /* 25 */ 23.6 .long do_mmuext_op 23.7 + .long do_policy_op /* 27 */ 23.8 .rept NR_hypercalls-((.-hypercall_table)/4) 23.9 .long do_ni_hypercall 23.10 .endr
24.1 --- a/xen/common/dom0_ops.c Sun Jun 19 17:05:55 2005 +0000 24.2 +++ b/xen/common/dom0_ops.c Mon Jun 20 22:28:08 2005 +0000 24.3 @@ -19,6 +19,7 @@ 24.4 #include <asm/current.h> 24.5 #include <public/dom0_ops.h> 24.6 #include <public/sched_ctl.h> 24.7 +#include <acm/acm_hooks.h> 24.8 24.9 extern long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op); 24.10 extern void arch_getdomaininfo_ctxt( 24.11 @@ -91,6 +92,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op) 24.12 { 24.13 long ret = 0; 24.14 dom0_op_t curop, *op = &curop; 24.15 + void *ssid = NULL; /* save security ptr between pre and post/fail hooks */ 24.16 24.17 if ( !IS_PRIV(current->domain) ) 24.18 return -EPERM; 24.19 @@ -101,6 +103,9 @@ long do_dom0_op(dom0_op_t *u_dom0_op) 24.20 if ( op->interface_version != DOM0_INTERFACE_VERSION ) 24.21 return -EACCES; 24.22 24.23 + if ( acm_pre_dom0_op(op, &ssid) ) 24.24 + return -EACCES; 24.25 + 24.26 switch ( op->cmd ) 24.27 { 24.28 24.29 @@ -357,6 +362,11 @@ long do_dom0_op(dom0_op_t *u_dom0_op) 24.30 ((d->domain_flags & DOMF_shutdown) ? DOMFLAGS_SHUTDOWN : 0) | 24.31 d->shutdown_code << DOMFLAGS_SHUTDOWNSHIFT; 24.32 24.33 + if (d->ssid != NULL) 24.34 + op->u.getdomaininfo.ssidref = ((struct acm_ssid_domain *)d->ssid)->ssidref; 24.35 + else 24.36 + op->u.getdomaininfo.ssidref = ACM_DEFAULT_SSID; 24.37 + 24.38 op->u.getdomaininfo.tot_pages = d->tot_pages; 24.39 op->u.getdomaininfo.max_pages = d->max_pages; 24.40 op->u.getdomaininfo.shared_info_frame = 24.41 @@ -493,7 +503,10 @@ long do_dom0_op(dom0_op_t *u_dom0_op) 24.42 ret = arch_do_dom0_op(op,u_dom0_op); 24.43 24.44 } 24.45 - 24.46 + if (!ret) 24.47 + acm_post_dom0_op(op, ssid); 24.48 + else 24.49 + acm_fail_dom0_op(op, ssid); 24.50 return ret; 24.51 } 24.52
25.1 --- a/xen/common/event_channel.c Sun Jun 19 17:05:55 2005 +0000 25.2 +++ b/xen/common/event_channel.c Mon Jun 20 22:28:08 2005 +0000 25.3 @@ -26,6 +26,7 @@ 25.4 25.5 #include <public/xen.h> 25.6 #include <public/event_channel.h> 25.7 +#include <acm/acm_hooks.h> 25.8 25.9 #define bucket_from_port(d,p) \ 25.10 ((d)->evtchn[(p)/EVTCHNS_PER_BUCKET]) 25.11 @@ -587,6 +588,9 @@ long do_event_channel_op(evtchn_op_t *uo 25.12 if ( copy_from_user(&op, uop, sizeof(op)) != 0 ) 25.13 return -EFAULT; 25.14 25.15 + if (acm_pre_event_channel(&op)) 25.16 + return -EACCES; 25.17 + 25.18 switch ( op.cmd ) 25.19 { 25.20 case EVTCHNOP_alloc_unbound:
26.1 --- a/xen/common/grant_table.c Sun Jun 19 17:05:55 2005 +0000 26.2 +++ b/xen/common/grant_table.c Mon Jun 20 22:28:08 2005 +0000 26.3 @@ -30,6 +30,7 @@ 26.4 #include <xen/sched.h> 26.5 #include <xen/shadow.h> 26.6 #include <xen/mm.h> 26.7 +#include <acm/acm_hooks.h> 26.8 26.9 #define PIN_FAIL(_lbl, _rc, _f, _a...) \ 26.10 do { \ 26.11 @@ -357,6 +358,11 @@ static int 26.12 return GNTST_bad_gntref; 26.13 } 26.14 26.15 + if (acm_pre_grant_map_ref(dom)) { 26.16 + (void)__put_user(GNTST_permission_denied, &uop->handle); 26.17 + return GNTST_permission_denied; 26.18 + } 26.19 + 26.20 if ( unlikely((rd = find_domain_by_id(dom)) == NULL) || 26.21 unlikely(ld == rd) ) 26.22 {
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/xen/common/policy_ops.c Mon Jun 20 22:28:08 2005 +0000 27.3 @@ -0,0 +1,117 @@ 27.4 +/****************************************************************************** 27.5 + *policy_ops.c 27.6 + * 27.7 + * Copyright (C) 2005 IBM Corporation 27.8 + * 27.9 + * Author: 27.10 + * Reiner Sailer <sailer@watson.ibm.com> 27.11 + * 27.12 + * This program is free software; you can redistribute it and/or 27.13 + * modify it under the terms of the GNU General Public License as 27.14 + * published by the Free Software Foundation, version 2 of the 27.15 + * License. 27.16 + * 27.17 + * Process policy command requests from guest OS. 27.18 + * 27.19 + */ 27.20 +#include <xen/config.h> 27.21 +#include <xen/types.h> 27.22 +#include <xen/lib.h> 27.23 +#include <xen/mm.h> 27.24 +#include <public/policy_ops.h> 27.25 +#include <xen/sched.h> 27.26 +#include <xen/event.h> 27.27 +#include <xen/trace.h> 27.28 +#include <xen/console.h> 27.29 +#include <asm/shadow.h> 27.30 +#include <public/sched_ctl.h> 27.31 +#include <acm/acm_hooks.h> 27.32 + 27.33 +/* function prototypes defined in acm/acm_policy.c */ 27.34 +int acm_set_policy(void *buf, u16 buf_size, u16 policy); 27.35 +int acm_get_policy(void *buf, u16 buf_size); 27.36 +int acm_dump_statistics(void *buf, u16 buf_size); 27.37 + 27.38 +typedef enum policyoperation { 27.39 + POLICY, /* access to policy interface (early drop) */ 27.40 + GETPOLICY, /* dump policy cache */ 27.41 + SETPOLICY, /* set policy cache (controls security) */ 27.42 + DUMPSTATS /* dump policy statistics */ 27.43 +} policyoperation_t; 27.44 + 27.45 +int 27.46 +acm_authorize_policyops(struct domain *d, policyoperation_t pops) 27.47 +{ 27.48 + /* currently, all policy management functions are restricted to privileged domains, 27.49 + * soon we will introduce finer-grained privileges for policy operations 27.50 + */ 27.51 + if (!IS_PRIV(d)) { 27.52 + printk("%s: Policy management authorization denied ERROR!\n", __func__); 27.53 + return ACM_ACCESS_DENIED; 27.54 + } 27.55 + return ACM_ACCESS_PERMITTED; 27.56 +} 27.57 + 27.58 +long do_policy_op(policy_op_t *u_policy_op) 27.59 +{ 27.60 + long ret = 0; 27.61 + policy_op_t curop, *op = &curop; 27.62 + 27.63 + /* check here policy decision for policy commands */ 27.64 + /* for now allow DOM0 only, later indepedently */ 27.65 + if (acm_authorize_policyops(current->domain, POLICY)) 27.66 + return -EACCES; 27.67 + 27.68 + if ( copy_from_user(op, u_policy_op, sizeof(*op)) ) 27.69 + return -EFAULT; 27.70 + 27.71 + if ( op->interface_version != POLICY_INTERFACE_VERSION ) 27.72 + return -EACCES; 27.73 + 27.74 + switch ( op->cmd ) 27.75 + { 27.76 + case POLICY_SETPOLICY: 27.77 + { 27.78 + if (acm_authorize_policyops(current->domain, SETPOLICY)) 27.79 + return -EACCES; 27.80 + printkd("%s: setting policy.\n", __func__); 27.81 + ret = acm_set_policy(op->u.setpolicy.pushcache, op->u.setpolicy.pushcache_size, op->u.setpolicy.policy_type); 27.82 + if (ret == ACM_OK) 27.83 + ret = 0; 27.84 + else 27.85 + ret = -ESRCH; 27.86 + } 27.87 + break; 27.88 + 27.89 + case POLICY_GETPOLICY: 27.90 + { 27.91 + if (acm_authorize_policyops(current->domain, GETPOLICY)) 27.92 + return -EACCES; 27.93 + printkd("%s: getting policy.\n", __func__); 27.94 + ret = acm_get_policy(op->u.getpolicy.pullcache, op->u.getpolicy.pullcache_size); 27.95 + if (ret == ACM_OK) 27.96 + ret = 0; 27.97 + else 27.98 + ret = -ESRCH; 27.99 + } 27.100 + break; 27.101 + 27.102 + case POLICY_DUMPSTATS: 27.103 + { 27.104 + if (acm_authorize_policyops(current->domain, DUMPSTATS)) 27.105 + return -EACCES; 27.106 + printkd("%s: dumping statistics.\n", __func__); 27.107 + ret = acm_dump_statistics(op->u.dumpstats.pullcache, op->u.dumpstats.pullcache_size); 27.108 + if (ret == ACM_OK) 27.109 + ret = 0; 27.110 + else 27.111 + ret = -ESRCH; 27.112 + } 27.113 + break; 27.114 + 27.115 + default: 27.116 + ret = -ESRCH; 27.117 + 27.118 + } 27.119 + return ret; 27.120 +}
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/xen/include/acm/acm_core.h Mon Jun 20 22:28:08 2005 +0000 28.3 @@ -0,0 +1,117 @@ 28.4 +/**************************************************************** 28.5 + * acm_core.h 28.6 + * 28.7 + * Copyright (C) 2005 IBM Corporation 28.8 + * 28.9 + * Author: 28.10 + * Reiner Sailer <sailer@watson.ibm.com> 28.11 + * 28.12 + * This program is free software; you can redistribute it and/or 28.13 + * modify it under the terms of the GNU General Public License as 28.14 + * published by the Free Software Foundation, version 2 of the 28.15 + * License. 28.16 + * 28.17 + * sHype header file describing core data types and constants 28.18 + * for the access control module and relevant policies 28.19 + * 28.20 + */ 28.21 +#ifndef _ACM_CORE_H 28.22 +#define _ACM_CORE_H 28.23 + 28.24 +#include <xen/spinlock.h> 28.25 +#include <public/acm.h> 28.26 +#include <public/policy_ops.h> 28.27 + 28.28 +/* Xen-internal representation of the binary policy */ 28.29 +struct acm_binary_policy { 28.30 + u16 primary_policy_code; 28.31 + u16 secondary_policy_code; 28.32 + void *primary_binary_policy; 28.33 + void *secondary_binary_policy; 28.34 + 28.35 +}; 28.36 + 28.37 +struct chwall_binary_policy { 28.38 + u16 max_types; 28.39 + u16 max_ssidrefs; 28.40 + u16 max_conflictsets; 28.41 + domaintype_t *ssidrefs; /* [max_ssidrefs][max_types] */ 28.42 + domaintype_t *conflict_aggregate_set; /* [max_types] */ 28.43 + domaintype_t *running_types; /* [max_types] */ 28.44 + domaintype_t *conflict_sets; /* [max_conflictsets][max_types]*/ 28.45 +}; 28.46 + 28.47 +struct ste_binary_policy { 28.48 + u16 max_types; 28.49 + u16 max_ssidrefs; 28.50 + domaintype_t *ssidrefs; /* [max_ssidrefs][max_types] */ 28.51 + atomic_t ec_eval_count, gt_eval_count; 28.52 + atomic_t ec_denied_count, gt_denied_count; 28.53 + atomic_t ec_cachehit_count, gt_cachehit_count; 28.54 +}; 28.55 + 28.56 +/* global acm policy */ 28.57 +extern struct acm_binary_policy acm_bin_pol; 28.58 +extern struct chwall_binary_policy chwall_bin_pol; 28.59 +extern struct ste_binary_policy ste_bin_pol; 28.60 +/* use the lock when reading / changing binary policy ! */ 28.61 +extern rwlock_t acm_bin_pol_rwlock; 28.62 + 28.63 +/* subject and object type definitions */ 28.64 +enum acm_datatype { DOMAIN }; 28.65 + 28.66 +/* defines number of access decisions to other domains can be cached 28.67 + * one entry per domain, TE does not distinguish evtchn or grant_table */ 28.68 +#define ACM_TE_CACHE_SIZE 8 28.69 +enum acm_ste_flag { VALID, FREE }; 28.70 + 28.71 +/* cache line: 28.72 + * if cache_line.valid==VALID, then 28.73 + * STE decision is cached as "permitted" 28.74 + * on domain cache_line.id 28.75 + */ 28.76 +struct acm_ste_cache_line { 28.77 + enum acm_ste_flag valid; 28.78 + domid_t id; 28.79 +}; 28.80 + 28.81 +/* general definition of a subject security id */ 28.82 +struct acm_ssid_domain { 28.83 + enum acm_datatype datatype; /* type of subject (e.g., partition) */ 28.84 + ssidref_t ssidref; /* combined security reference */ 28.85 + void *primary_ssid; /* primary policy ssid part (e.g. chinese wall) */ 28.86 + void *secondary_ssid; /* secondary policy ssid part (e.g. type enforcement) */ 28.87 + struct domain *subject; /* backpointer to subject structure */ 28.88 + domid_t domainid; /* replicate id */ 28.89 +}; 28.90 + 28.91 +/* chinese wall ssid type */ 28.92 +struct chwall_ssid { 28.93 + ssidref_t chwall_ssidref; 28.94 +}; 28.95 + 28.96 +/* simple type enforcement ssid type */ 28.97 +struct ste_ssid { 28.98 + ssidref_t ste_ssidref; 28.99 + struct acm_ste_cache_line ste_cache[ACM_TE_CACHE_SIZE]; /* decision cache */ 28.100 +}; 28.101 + 28.102 +/* macros to access ssidref for primary / secondary policy 28.103 + * primary ssidref = lower 16 bit 28.104 + * secondary ssidref = higher 16 bit 28.105 + */ 28.106 +#define GET_SSIDREF(POLICY, ssidref) \ 28.107 + ((POLICY) == acm_bin_pol.primary_policy_code) ? \ 28.108 + ((ssidref) & 0xffff) : ((ssidref) >> 16) 28.109 + 28.110 +/* macros to access ssid pointer for primary / secondary policy */ 28.111 +#define GET_SSIDP(POLICY, ssid) \ 28.112 + ((POLICY) == acm_bin_pol.primary_policy_code) ? \ 28.113 + ((ssid)->primary_ssid) : ((ssid)->secondary_ssid) 28.114 + 28.115 +/* protos */ 28.116 +int acm_init_domain_ssid(domid_t id, ssidref_t ssidref); 28.117 +int acm_free_domain_ssid(struct acm_ssid_domain *ssid); 28.118 + 28.119 +#endif 28.120 +
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 29.2 +++ b/xen/include/acm/acm_endian.h Mon Jun 20 22:28:08 2005 +0000 29.3 @@ -0,0 +1,88 @@ 29.4 +/**************************************************************** 29.5 + * acm_endian.h 29.6 + * 29.7 + * Copyright (C) 2005 IBM Corporation 29.8 + * 29.9 + * Author: 29.10 + * Stefan Berger <stefanb@watson.ibm.com> 29.11 + * 29.12 + * Contributions: 29.13 + * Reiner Sailer <sailer@watson.ibm.com> 29.14 + * 29.15 + * This program is free software; you can redistribute it and/or 29.16 + * modify it under the terms of the GNU General Public License as 29.17 + * published by the Free Software Foundation, version 2 of the 29.18 + * License. 29.19 + * 29.20 + * sHype header file defining endian-dependent functions for the 29.21 + * big-endian policy interface 29.22 + * 29.23 + */ 29.24 +#ifndef _ACM_ENDIAN_H 29.25 +#define _ACM_ENDIAN_H 29.26 + 29.27 +/* don't use these functions in performance critical sections! */ 29.28 + 29.29 +/* set during initialization by testing */ 29.30 +extern u8 little_endian; 29.31 + 29.32 +static inline u32 ntohl(u32 x) 29.33 +{ 29.34 + if (little_endian) 29.35 + return 29.36 + ( (((x) >> 24) & 0xff )| 29.37 + (((x) >> 8) & 0xff00 )| 29.38 + (((x) << 8) & 0xff0000 )| 29.39 + (((x) << 24) & 0xff000000) ); 29.40 + else 29.41 + return x; 29.42 +} 29.43 + 29.44 +static inline u16 ntohs(u16 x) 29.45 +{ 29.46 + if (little_endian) 29.47 + return 29.48 + ( (((x) >> 8) & 0xff )| 29.49 + (((x) << 8) & 0xff00 ) ); 29.50 + else 29.51 + return x; 29.52 +} 29.53 + 29.54 +#define htonl(x) ntohl(x) 29.55 +#define htons(x) ntohs(x) 29.56 + 29.57 +static inline void arrcpy16(u16 *dest, const u16 *src, size_t n) 29.58 +{ 29.59 + unsigned int i = 0; 29.60 + while (i < n) { 29.61 + dest[i] = htons(src[i]); 29.62 + i++; 29.63 + } 29.64 +} 29.65 + 29.66 +static inline void arrcpy32(u32 *dest, const u32 *src, size_t n) 29.67 +{ 29.68 + unsigned int i = 0; 29.69 + while (i < n) { 29.70 + dest[i] = htonl(src[i]); 29.71 + i++; 29.72 + } 29.73 +} 29.74 + 29.75 +static inline void arrcpy(void *dest, const void *src, unsigned int elsize, size_t n) 29.76 +{ 29.77 + switch (elsize) { 29.78 + case sizeof(u16): 29.79 + arrcpy16((u16 *)dest, (u16 *)src, n); 29.80 + break; 29.81 + 29.82 + case sizeof(u32): 29.83 + arrcpy32((u32 *)dest, (u32 *)src, n); 29.84 + break; 29.85 + 29.86 + default: 29.87 + memcpy(dest, src, elsize*n); 29.88 + } 29.89 +} 29.90 + 29.91 +#endif
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/xen/include/acm/acm_hooks.h Mon Jun 20 22:28:08 2005 +0000 30.3 @@ -0,0 +1,337 @@ 30.4 +/**************************************************************** 30.5 + * acm_hooks.h 30.6 + * 30.7 + * Copyright (C) 2005 IBM Corporation 30.8 + * 30.9 + * Author: 30.10 + * Reiner Sailer <sailer@watson.ibm.com> 30.11 + * 30.12 + * This program is free software; you can redistribute it and/or 30.13 + * modify it under the terms of the GNU General Public License as 30.14 + * published by the Free Software Foundation, version 2 of the 30.15 + * License. 30.16 + * 30.17 + * acm header file implementing the global (policy-independent) 30.18 + * sHype hooks that are called throughout Xen. 30.19 + * 30.20 + */ 30.21 +#ifndef _ACM_HOOKS_H 30.22 +#define _ACM_HOOKS_H 30.23 + 30.24 +#include <xen/config.h> 30.25 +#include <xen/errno.h> 30.26 +#include <xen/types.h> 30.27 +#include <xen/lib.h> 30.28 +#include <xen/delay.h> 30.29 +#include <xen/sched.h> 30.30 +#include <public/acm.h> 30.31 +#include <acm/acm_core.h> 30.32 +#include <public/dom0_ops.h> 30.33 +#include <public/event_channel.h> 30.34 +#include <asm/current.h> 30.35 + 30.36 +/* if ACM_TRACE_MODE defined, all hooks should 30.37 + * print a short trace message */ 30.38 +/* #define ACM_TRACE_MODE */ 30.39 + 30.40 +#ifdef ACM_TRACE_MODE 30.41 +# define traceprintk(fmt, args...) printk(fmt,## args) 30.42 +#else 30.43 +# define traceprintk(fmt, args...) 30.44 +#endif 30.45 + 30.46 +/* global variables */ 30.47 +extern struct acm_operations *acm_primary_ops; 30.48 +extern struct acm_operations *acm_secondary_ops; 30.49 + 30.50 +/********************************************************************************************** 30.51 + * HOOK structure and meaning (justifies a few words about our model): 30.52 + * 30.53 + * General idea: every policy-controlled system operation is reflected in a 30.54 + * transaction in the system's security state 30.55 + * 30.56 + * Keeping the security state consistent requires "atomic" transactions. 30.57 + * The name of the hooks to place around policy-controlled transactions 30.58 + * reflects this. If authorizations do not involve security state changes, 30.59 + * then and only then POST and FAIL hooks remain empty since we don't care 30.60 + * about the eventual outcome of the operation from a security viewpoint. 30.61 + * 30.62 + * PURPOSE of hook types: 30.63 + * ====================== 30.64 + * PRE-Hooks 30.65 + * a) general authorization to guard a controlled system operation 30.66 + * b) prepare security state change (means: fail hook must be able to "undo" this) 30.67 + * 30.68 + * POST-Hooks 30.69 + * a) commit prepared state change 30.70 + * 30.71 + * FAIL-Hooks 30.72 + * a) roll-back prepared security state change from PRE-Hook 30.73 + * 30.74 + * 30.75 + * PLACEMENT of hook types: 30.76 + * ======================== 30.77 + * PRE-Hooks must be called: 30.78 + * a) before a guarded/controlled system operation is started 30.79 + * (return is ACM_ACCESS_PERMITTED or ACM_ACCESS_DENIED or error) 30.80 + * --> operation must be aborted if return is != ACM_ACCESS_PERMITTED 30.81 + * 30.82 + * POST-Hooks must be called: 30.83 + * a) after successful transaction (no return value; commit shall never fail) 30.84 + * 30.85 + * FAIL-Hooks must be called: 30.86 + * a) if system transaction (operation) fails somewhen after calling the PRE-hook 30.87 + * (obviously the POST-Hook is not called in this case) 30.88 + * b) if another (secondary) policy denies access in its PRE-Hook 30.89 + * (policy layering is useful but requires additional handling) 30.90 + * 30.91 + * 30.92 + * 30.93 + * Hook model from a security transaction viewpoint: 30.94 + * 30.95 + * start-sys-ops--> prepare ----succeed-----> commit --> sys-ops success 30.96 + * (pre-hook) \ (post-hook) 30.97 + * \ 30.98 + * fail 30.99 + * \ 30.100 + * \ 30.101 + * roll-back 30.102 + * (fail-hook) 30.103 + * \ 30.104 + * sys-ops error 30.105 + * 30.106 + *************************************************************************************************/ 30.107 + 30.108 +struct acm_operations { 30.109 + /* policy management functions (must always be defined!) */ 30.110 + int (*init_domain_ssid) (void **ssid, ssidref_t ssidref); 30.111 + void (*free_domain_ssid) (void *ssid); 30.112 + int (*dump_binary_policy) (u8 *buffer, u16 buf_size); 30.113 + int (*set_binary_policy) (u8 *buffer, u16 buf_size); 30.114 + int (*dump_statistics) (u8 *buffer, u16 buf_size); 30.115 + /* domain management control hooks (can be NULL) */ 30.116 + int (*pre_domain_create) (void *subject_ssid, ssidref_t ssidref); 30.117 + void (*post_domain_create) (domid_t domid, ssidref_t ssidref); 30.118 + void (*fail_domain_create) (void *subject_ssid, ssidref_t ssidref); 30.119 + void (*post_domain_destroy) (void *object_ssid, domid_t id); 30.120 + /* event channel control hooks (can be NULL) */ 30.121 + int (*pre_eventchannel_unbound) (domid_t id); 30.122 + void (*fail_eventchannel_unbound) (domid_t id); 30.123 + int (*pre_eventchannel_interdomain) (domid_t id1, domid_t id2); 30.124 + int (*fail_eventchannel_interdomain) (domid_t id1, domid_t id2); 30.125 + /* grant table control hooks (can be NULL) */ 30.126 + int (*pre_grant_map_ref) (domid_t id); 30.127 + void (*fail_grant_map_ref) (domid_t id); 30.128 + int (*pre_grant_setup) (domid_t id); 30.129 + void (*fail_grant_setup) (domid_t id); 30.130 +}; 30.131 + 30.132 +static inline int acm_pre_domain_create (void *subject_ssid, ssidref_t ssidref) 30.133 +{ 30.134 + if ((acm_primary_ops->pre_domain_create != NULL) && 30.135 + acm_primary_ops->pre_domain_create (subject_ssid, ssidref)) 30.136 + return ACM_ACCESS_DENIED; 30.137 + else if ((acm_secondary_ops->pre_domain_create != NULL) && 30.138 + acm_secondary_ops->pre_domain_create (subject_ssid, ssidref)) { 30.139 + /* roll-back primary */ 30.140 + if (acm_primary_ops->fail_domain_create != NULL) 30.141 + acm_primary_ops->fail_domain_create (subject_ssid, ssidref); 30.142 + return ACM_ACCESS_DENIED; 30.143 + } else 30.144 + return ACM_ACCESS_PERMITTED; 30.145 +} 30.146 + 30.147 +static inline void acm_post_domain_create (domid_t domid, ssidref_t ssidref) 30.148 +{ 30.149 + if (acm_primary_ops->post_domain_create != NULL) 30.150 + acm_primary_ops->post_domain_create (domid, ssidref); 30.151 + if (acm_secondary_ops->post_domain_create != NULL) 30.152 + acm_secondary_ops->post_domain_create (domid, ssidref); 30.153 +} 30.154 + 30.155 +static inline void acm_fail_domain_create (void *subject_ssid, ssidref_t ssidref) 30.156 +{ 30.157 + if (acm_primary_ops->fail_domain_create != NULL) 30.158 + acm_primary_ops->fail_domain_create (subject_ssid, ssidref); 30.159 + if (acm_secondary_ops->fail_domain_create != NULL) 30.160 + acm_secondary_ops->fail_domain_create (subject_ssid, ssidref); 30.161 +} 30.162 + 30.163 +static inline void acm_post_domain_destroy (void *object_ssid, domid_t id) 30.164 +{ 30.165 + if (acm_primary_ops->post_domain_destroy != NULL) 30.166 + acm_primary_ops->post_domain_destroy (object_ssid, id); 30.167 + if (acm_secondary_ops->post_domain_destroy != NULL) 30.168 + acm_secondary_ops->post_domain_destroy (object_ssid, id); 30.169 + return; 30.170 +} 30.171 + 30.172 +/* event channel ops */ 30.173 + 30.174 +static inline int acm_pre_eventchannel_unbound (domid_t id) 30.175 +{ 30.176 + if ((acm_primary_ops->pre_eventchannel_unbound != NULL) && 30.177 + acm_primary_ops->pre_eventchannel_unbound (id)) 30.178 + return ACM_ACCESS_DENIED; 30.179 + else if ((acm_secondary_ops->pre_eventchannel_unbound != NULL) && 30.180 + acm_secondary_ops->pre_eventchannel_unbound (id)) { 30.181 + /* roll-back primary */ 30.182 + if (acm_primary_ops->fail_eventchannel_unbound != NULL) 30.183 + acm_primary_ops->fail_eventchannel_unbound (id); 30.184 + return ACM_ACCESS_DENIED; 30.185 + } else 30.186 + return ACM_ACCESS_PERMITTED; 30.187 +} 30.188 + 30.189 +static inline int acm_pre_eventchannel_interdomain (domid_t id1, domid_t id2) 30.190 +{ 30.191 + if ((acm_primary_ops->pre_eventchannel_interdomain != NULL) && 30.192 + acm_primary_ops->pre_eventchannel_interdomain (id1, id2)) 30.193 + return ACM_ACCESS_DENIED; 30.194 + else if ((acm_secondary_ops->pre_eventchannel_interdomain != NULL) && 30.195 + acm_secondary_ops->pre_eventchannel_interdomain (id1, id2)) { 30.196 + /* roll-back primary */ 30.197 + if (acm_primary_ops->fail_eventchannel_interdomain != NULL) 30.198 + acm_primary_ops->fail_eventchannel_interdomain (id1, id2); 30.199 + return ACM_ACCESS_DENIED; 30.200 + } else 30.201 + return ACM_ACCESS_PERMITTED; 30.202 +} 30.203 + 30.204 +/************ Xen inline hooks ***************/ 30.205 + 30.206 +/* small macro to make the hooks more readable 30.207 + * (eliminates hooks if NULL policy is active) 30.208 + */ 30.209 +#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) 30.210 +static inline int acm_pre_dom0_op(dom0_op_t *op, void **ssid) 30.211 +{ return 0; } 30.212 +#else 30.213 +static inline int acm_pre_dom0_op(dom0_op_t *op, void **ssid) 30.214 +{ 30.215 + int ret = -EACCES; 30.216 + struct domain *d; 30.217 + 30.218 + switch(op->cmd) { 30.219 + case DOM0_CREATEDOMAIN: 30.220 + ret = acm_pre_domain_create(current->domain->ssid, op->u.createdomain.ssidref); 30.221 + break; 30.222 + case DOM0_DESTROYDOMAIN: 30.223 + d = find_domain_by_id(op->u.destroydomain.domain); 30.224 + if (d != NULL) { 30.225 + *ssid = d->ssid; /* save for post destroy when d is gone */ 30.226 + /* no policy-specific hook */ 30.227 + put_domain(d); 30.228 + ret = 0; 30.229 + } 30.230 + break; 30.231 + default: 30.232 + ret = 0; /* ok */ 30.233 + } 30.234 + return ret; 30.235 +} 30.236 +#endif 30.237 + 30.238 + 30.239 +#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) 30.240 +static inline void acm_post_dom0_op(dom0_op_t *op, void *ssid) 30.241 +{ return; } 30.242 +#else 30.243 +static inline void acm_post_dom0_op(dom0_op_t *op, void *ssid) 30.244 +{ 30.245 + switch(op->cmd) { 30.246 + case DOM0_CREATEDOMAIN: 30.247 + /* initialialize shared sHype security labels for new domain */ 30.248 + acm_init_domain_ssid(op->u.createdomain.domain, op->u.createdomain.ssidref); 30.249 + acm_post_domain_create(op->u.createdomain.domain, op->u.createdomain.ssidref); 30.250 + break; 30.251 + case DOM0_DESTROYDOMAIN: 30.252 + acm_post_domain_destroy(ssid, op->u.destroydomain.domain); 30.253 + /* free security ssid for the destroyed domain (also if running null policy */ 30.254 + acm_free_domain_ssid((struct acm_ssid_domain *)ssid); 30.255 + break; 30.256 + } 30.257 +} 30.258 +#endif 30.259 + 30.260 + 30.261 +#if (ACM_USE_SECURITY_POLICy == ACM_NULL_POLICY) 30.262 +static inline void acm_fail_dom0_op(dom0_op_t *op, void *ssid) 30.263 +{ return; } 30.264 +#else 30.265 +static inline void acm_fail_dom0_op(dom0_op_t *op, void *ssid) 30.266 +{ 30.267 + switch(op->cmd) { 30.268 + case DOM0_CREATEDOMAIN: 30.269 + acm_fail_domain_create(current->domain->ssid, op->u.createdomain.ssidref); 30.270 + break; 30.271 + } 30.272 +} 30.273 +#endif 30.274 + 30.275 + 30.276 +#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) 30.277 +static inline int acm_pre_event_channel(evtchn_op_t *op) 30.278 +{ return 0; } 30.279 +#else 30.280 +static inline int acm_pre_event_channel(evtchn_op_t *op) 30.281 +{ 30.282 + int ret = -EACCES; 30.283 + 30.284 + switch(op->cmd) { 30.285 + case EVTCHNOP_alloc_unbound: 30.286 + ret = acm_pre_eventchannel_unbound(op->u.alloc_unbound.dom); 30.287 + break; 30.288 + case EVTCHNOP_bind_interdomain: 30.289 + ret = acm_pre_eventchannel_interdomain(op->u.bind_interdomain.dom1, op->u.bind_interdomain.dom2); 30.290 + break; 30.291 + default: 30.292 + ret = 0; /* ok */ 30.293 + } 30.294 + return ret; 30.295 +} 30.296 +#endif 30.297 + 30.298 +#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) 30.299 +static inline int acm_pre_grant_map_ref(domid_t id) 30.300 +{ return 0; } 30.301 +#else 30.302 +static inline int acm_pre_grant_map_ref (domid_t id) 30.303 +{ 30.304 + if ((acm_primary_ops->pre_grant_map_ref != NULL) && 30.305 + acm_primary_ops->pre_grant_map_ref (id)) 30.306 + return ACM_ACCESS_DENIED; 30.307 + else if ((acm_secondary_ops->pre_grant_map_ref != NULL) && 30.308 + acm_secondary_ops->pre_grant_map_ref (id)) { 30.309 + /* roll-back primary */ 30.310 + if (acm_primary_ops->fail_grant_map_ref != NULL) 30.311 + acm_primary_ops->fail_grant_map_ref (id); 30.312 + return ACM_ACCESS_DENIED; 30.313 + } else 30.314 + return ACM_ACCESS_PERMITTED; 30.315 +} 30.316 +#endif 30.317 + 30.318 + 30.319 +#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) 30.320 +static inline int acm_pre_grant_setup(domid_t id) 30.321 +{ return 0; } 30.322 +#else 30.323 +static inline int acm_pre_grant_setup (domid_t id) 30.324 +{ 30.325 + if ((acm_primary_ops->pre_grant_setup != NULL) && 30.326 + acm_primary_ops->pre_grant_setup (id)) 30.327 + return ACM_ACCESS_DENIED; 30.328 + else if ((acm_secondary_ops->pre_grant_setup != NULL) && 30.329 + acm_secondary_ops->pre_grant_setup (id)) { 30.330 + /* roll-back primary */ 30.331 + if (acm_primary_ops->fail_grant_setup != NULL) 30.332 + acm_primary_ops->fail_grant_setup (id); 30.333 + return ACM_ACCESS_DENIED; 30.334 + } else 30.335 + return ACM_ACCESS_PERMITTED; 30.336 +} 30.337 +#endif 30.338 + 30.339 + 30.340 +#endif
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 31.2 +++ b/xen/include/public/acm.h Mon Jun 20 22:28:08 2005 +0000 31.3 @@ -0,0 +1,161 @@ 31.4 +/**************************************************************** 31.5 + * acm.h 31.6 + * 31.7 + * Copyright (C) 2005 IBM Corporation 31.8 + * 31.9 + * Author: 31.10 + * Reiner Sailer <sailer@watson.ibm.com> 31.11 + * 31.12 + * Contributors: 31.13 + * Stefan Berger <stefanb@watson.ibm.com> 31.14 + * added network byte order support for binary policies 31.15 + * 31.16 + * This program is free software; you can redistribute it and/or 31.17 + * modify it under the terms of the GNU General Public License as 31.18 + * published by the Free Software Foundation, version 2 of the 31.19 + * License. 31.20 + * 31.21 + * sHype general access control module header file. 31.22 + * here are all definitions that are shared between 31.23 + * xen-core, guest-kernels, and applications. 31.24 + * 31.25 + * todo: move from static policy choice to compile option. 31.26 + */ 31.27 + 31.28 +#ifndef _XEN_PUBLIC_SHYPE_H 31.29 +#define _XEN_PUBLIC_SHYPE_H 31.30 + 31.31 +#include "xen.h" 31.32 +#include "sched_ctl.h" 31.33 + 31.34 +/* if ACM_DEBUG defined, all hooks should 31.35 + * print a short trace message (comment it out 31.36 + * when not in testing mode ) 31.37 + */ 31.38 +/* #define ACM_DEBUG */ 31.39 + 31.40 +#ifdef ACM_DEBUG 31.41 +# define printkd(fmt, args...) printk(fmt,## args) 31.42 +#else 31.43 +# define printkd(fmt, args...) 31.44 +#endif 31.45 + 31.46 +/* default ssid reference value if not supplied */ 31.47 +#define ACM_DEFAULT_SSID 0xffffffff 31.48 +#define ACM_DEFAULT_LOCAL_SSID 0xffff 31.49 + 31.50 +/* Internal ACM ERROR types */ 31.51 +#define ACM_OK 0 31.52 +#define ACM_UNDEF -1 31.53 +#define ACM_INIT_SSID_ERROR -2 31.54 +#define ACM_INIT_SOID_ERROR -3 31.55 +#define ACM_ERROR -4 31.56 + 31.57 +/* External ACCESS DECISIONS */ 31.58 +#define ACM_ACCESS_PERMITTED 0 31.59 +#define ACM_ACCESS_DENIED -111 31.60 +#define ACM_NULL_POINTER_ERROR -200 31.61 + 31.62 +#define ACM_MAX_POLICY 3 31.63 + 31.64 +#define ACM_NULL_POLICY 0 31.65 +#define ACM_CHINESE_WALL_POLICY 1 31.66 +#define ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY 2 31.67 +#define ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY 3 31.68 + 31.69 +/* policy: */ 31.70 +#define ACM_POLICY_NAME(X) \ 31.71 + (X == ACM_NULL_POLICY) ? "NULL policy" : \ 31.72 + (X == ACM_CHINESE_WALL_POLICY) ? "CHINESE WALL policy" : \ 31.73 + (X == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) ? "SIMPLE TYPE ENFORCEMENT policy" : \ 31.74 + (X == ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) ? "CHINESE WALL AND SIMPLE TYPE ENFORCEMENT policy" : \ 31.75 + "UNDEFINED policy" 31.76 + 31.77 +#ifndef ACM_USE_SECURITY_POLICY 31.78 +#define ACM_USE_SECURITY_POLICY ACM_NULL_POLICY 31.79 +#endif 31.80 + 31.81 +/* defines a ssid reference used by xen */ 31.82 +typedef u32 ssidref_t; 31.83 + 31.84 +/* -------security policy relevant type definitions-------- */ 31.85 + 31.86 +/* type identifier; compares to "equal" or "not equal" */ 31.87 +typedef u16 domaintype_t; 31.88 + 31.89 +/* CHINESE WALL POLICY DATA STRUCTURES 31.90 + * 31.91 + * current accumulated conflict type set: 31.92 + * When a domain is started and has a type that is in 31.93 + * a conflict set, the conflicting types are incremented in 31.94 + * the aggregate set. When a domain is destroyed, the 31.95 + * conflicting types to its type are decremented. 31.96 + * If a domain has multiple types, this procedure works over 31.97 + * all those types. 31.98 + * 31.99 + * conflict_aggregate_set[i] holds the number of 31.100 + * running domains that have a conflict with type i. 31.101 + * 31.102 + * running_types[i] holds the number of running domains 31.103 + * that include type i in their ssidref-referenced type set 31.104 + * 31.105 + * conflict_sets[i][j] is "0" if type j has no conflict 31.106 + * with type i and is "1" otherwise. 31.107 + */ 31.108 +/* high-16 = version, low-16 = check magic */ 31.109 +#define ACM_MAGIC 0x0001debc 31.110 + 31.111 +/* each offset in bytes from start of the struct they 31.112 + * the are part of */ 31.113 +/* each buffer consists of all policy information for 31.114 + * the respective policy given in the policy code 31.115 + */ 31.116 +struct acm_policy_buffer { 31.117 + u32 magic; 31.118 + u32 policyversion; 31.119 + u32 len; 31.120 + u16 primary_policy_code; 31.121 + u16 primary_buffer_offset; 31.122 + u16 secondary_policy_code; 31.123 + u16 secondary_buffer_offset; 31.124 +}; 31.125 + 31.126 +struct acm_chwall_policy_buffer { 31.127 + u16 policy_code; 31.128 + u16 chwall_max_types; 31.129 + u16 chwall_max_ssidrefs; 31.130 + u16 chwall_max_conflictsets; 31.131 + u16 chwall_ssid_offset; 31.132 + u16 chwall_conflict_sets_offset; 31.133 + u16 chwall_running_types_offset; 31.134 + u16 chwall_conflict_aggregate_offset; 31.135 +}; 31.136 + 31.137 +struct acm_ste_policy_buffer { 31.138 + u16 policy_code; 31.139 + u16 ste_max_types; 31.140 + u16 ste_max_ssidrefs; 31.141 + u16 ste_ssid_offset; 31.142 +}; 31.143 + 31.144 +struct acm_stats_buffer { 31.145 + u32 magic; 31.146 + u32 policyversion; 31.147 + u32 len; 31.148 + u16 primary_policy_code; 31.149 + u16 primary_stats_offset; 31.150 + u16 secondary_policy_code; 31.151 + u16 secondary_stats_offset; 31.152 +}; 31.153 + 31.154 +struct acm_ste_stats_buffer { 31.155 + u32 ec_eval_count; 31.156 + u32 gt_eval_count; 31.157 + u32 ec_denied_count; 31.158 + u32 gt_denied_count; 31.159 + u32 ec_cachehit_count; 31.160 + u32 gt_cachehit_count; 31.161 +}; 31.162 + 31.163 + 31.164 +#endif
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/xen/include/public/acm_dom0_setup.h Mon Jun 20 22:28:08 2005 +0000 32.3 @@ -0,0 +1,34 @@ 32.4 +/**************************************************************** 32.5 + * acm_dom0_setup.h 32.6 + * 32.7 + * Copyright (C) 2005 IBM Corporation 32.8 + * 32.9 + * Author: 32.10 + * Reiner Sailer <sailer@watson.ibm.com> 32.11 + * 32.12 + * Includes necessary definitions to bring-up dom0 32.13 + */ 32.14 +#include <acm/acm_hooks.h> 32.15 + 32.16 +extern int acm_init(void); 32.17 + 32.18 +#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) 32.19 + 32.20 +static inline void acm_post_domain0_create(domid_t domid) 32.21 +{ 32.22 + return; 32.23 +} 32.24 + 32.25 +#else 32.26 + 32.27 +/* predefined ssidref for DOM0 used by xen when creating DOM0 */ 32.28 +#define ACM_DOM0_SSIDREF 0 32.29 + 32.30 +static inline void acm_post_domain0_create(domid_t domid) 32.31 +{ 32.32 + /* initialialize shared sHype security labels for new domain */ 32.33 + acm_init_domain_ssid(domid, ACM_DOM0_SSIDREF); 32.34 + acm_post_domain_create(domid, ACM_DOM0_SSIDREF); 32.35 +} 32.36 + 32.37 +#endif
33.1 --- a/xen/include/public/dom0_ops.h Sun Jun 19 17:05:55 2005 +0000 33.2 +++ b/xen/include/public/dom0_ops.h Mon Jun 20 22:28:08 2005 +0000 33.3 @@ -43,6 +43,8 @@ typedef struct sched_adjdom_cmd dom0_adj 33.4 33.5 #define DOM0_CREATEDOMAIN 8 33.6 typedef struct { 33.7 + /* IN parameters */ 33.8 + u32 ssidref; 33.9 /* IN/OUT parameters. */ 33.10 /* Identifier for new domain (auto-allocate if zero is specified). */ 33.11 domid_t domain; 33.12 @@ -88,6 +90,7 @@ typedef struct { 33.13 u32 n_vcpu; 33.14 s32 vcpu_to_cpu[MAX_VIRT_CPUS]; /* current mapping */ 33.15 cpumap_t cpumap[MAX_VIRT_CPUS]; /* allowable mapping */ 33.16 + u32 ssidref; 33.17 } dom0_getdomaininfo_t; 33.18 33.19 #define DOM0_SETDOMAININFO 13
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/xen/include/public/policy_ops.h Mon Jun 20 22:28:08 2005 +0000 34.3 @@ -0,0 +1,74 @@ 34.4 +/****************************************************************************** 34.5 + * policy_ops.h 34.6 + * 34.7 + * Copyright (C) 2005 IBM Corporation 34.8 + * 34.9 + * Author: 34.10 + * Reiner Sailer <sailer@watson.ibm.com> 34.11 + * 34.12 + * This program is free software; you can redistribute it and/or 34.13 + * modify it under the terms of the GNU General Public License as 34.14 + * published by the Free Software Foundation, version 2 of the 34.15 + * License. 34.16 + * 34.17 + * Process policy command requests from guest OS. 34.18 + * access checked by policy; not restricted to DOM0 34.19 + * 34.20 + */ 34.21 + 34.22 + 34.23 +#ifndef __XEN_PUBLIC_POLICY_OPS_H__ 34.24 +#define __XEN_PUBLIC_POLICY_OPS_H__ 34.25 + 34.26 +#include "xen.h" 34.27 +#include "sched_ctl.h" 34.28 + 34.29 +/* 34.30 + * Make sure you increment the interface version whenever you modify this file! 34.31 + * This makes sure that old versions of policy tools will stop working in a 34.32 + * well-defined way (rather than crashing the machine, for instance). 34.33 + */ 34.34 +#define POLICY_INTERFACE_VERSION 0xAAAA0001 34.35 + 34.36 +/************************************************************************/ 34.37 + 34.38 +#define POLICY_SETPOLICY 4 34.39 +typedef struct { 34.40 + /* IN variables. */ 34.41 + u16 policy_type; 34.42 + u16 padding1; 34.43 + /* OUT variables */ 34.44 + void *pushcache; 34.45 + u16 pushcache_size; 34.46 +} PACKED policy_setpolicy_t; 34.47 + 34.48 + 34.49 +#define POLICY_GETPOLICY 5 34.50 +typedef struct { 34.51 + /* IN variables. */ 34.52 + u16 policy_type; 34.53 + u16 padding1; 34.54 + /* OUT variables */ 34.55 + void *pullcache; 34.56 + u16 pullcache_size; 34.57 +} PACKED policy_getpolicy_t; 34.58 + 34.59 +#define POLICY_DUMPSTATS 6 34.60 +typedef struct { 34.61 + void *pullcache; 34.62 + u16 pullcache_size; 34.63 +} PACKED policy_dumpstats_t; 34.64 + 34.65 + 34.66 +typedef struct { 34.67 + u32 cmd; /* 0 */ 34.68 + u32 interface_version; /* 4 */ /* POLICY_INTERFACE_VERSION */ 34.69 + union { /* 8 */ 34.70 + u32 dummy[14]; /* 72bytes */ 34.71 + policy_setpolicy_t setpolicy; 34.72 + policy_getpolicy_t getpolicy; 34.73 + policy_dumpstats_t dumpstats; 34.74 + } PACKED u; 34.75 +} PACKED policy_op_t; /* 80 bytes */ 34.76 + 34.77 +#endif /* __XEN_PUBLIC_POLICY_OPS_H__ */
35.1 --- a/xen/include/public/xen.h Sun Jun 19 17:05:55 2005 +0000 35.2 +++ b/xen/include/public/xen.h Mon Jun 20 22:28:08 2005 +0000 35.3 @@ -58,6 +58,7 @@ 35.4 #define __HYPERVISOR_boot_vcpu 24 35.5 #define __HYPERVISOR_set_segment_base 25 /* x86/64 only */ 35.6 #define __HYPERVISOR_mmuext_op 26 35.7 +#define __HYPERVISOR_policy_op 27 35.8 35.9 /* 35.10 * VIRTUAL INTERRUPTS
36.1 --- a/xen/include/xen/sched.h Sun Jun 19 17:05:55 2005 +0000 36.2 +++ b/xen/include/xen/sched.h Mon Jun 20 22:28:08 2005 +0000 36.3 @@ -137,6 +137,8 @@ struct domain 36.4 cpumask_t cpumask; 36.5 36.6 struct arch_domain arch; 36.7 + 36.8 + void *ssid; /* sHype security subject identifier */ 36.9 }; 36.10 36.11 struct domain_setup_info