bitkeeper revision 1.1720 (42b7bb86ag6KD5OEx2v6YdSnS1BhGQ)

Merge freefall.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-unstable.bk
into freefall.cl.cam.ac.uk:/auto/groups/xeno/users/iap10/xeno-clone/xen-unstable.bk
This commit is contained in:
iap10@freefall.cl.cam.ac.uk committed 2005-06-21 07:02:30 +00:00
commit 22e32f8c3c
107 files changed
+7147 -606

No files matched your search

+30 -1
View File
@@ -21,6 +21,7 @@
420b949cy9ZGzED74Fz_DaWlK7tT4g docs/misc/crashdb.txt
4251a1f82AexscYEiF4Iku8Gc_kWfQ docs/misc/grant-tables.txt
424d462b5GuApQ_NyMsRFt9LbrsWow docs/misc/sedf_scheduler_mini-HOWTO.txt
42b7434c-M2l4Og0klGf6xSAARqa2w docs/misc/shype4xen_readme.txt
40d6ccbfKKBq8jE0ula4eHEzBiQuDA docs/misc/xen_config.html
410a4c2bAO_m_l4RsiiPHnZ4ixHWbQ docs/misc/xend.tex
3f9e7d564bWFB-Czjv1qdmE6o0GqNg docs/src/interface.tex
@@ -777,6 +778,16 @@
40c9c469kT0H9COWzA4XzPBjWK0WsA tools/misc/netfix
4022a73cEKvrYe_DVZW2JlAxobg9wg tools/misc/nsplitd/Makefile
4022a73cKms4Oq030x2JBzUB426lAQ tools/misc/nsplitd/nsplitd.c
42b74436oXEaaUH_dPcGFviMiwNgCQ tools/misc/policyprocessor/SecurityLabel.java
42b74436fIW8ZI3pUpu13-Ox6G2cOA tools/misc/policyprocessor/SecurityPolicySpec.xsd
42b74436T4CN4HMWsuaHD2zS8jY1BA tools/misc/policyprocessor/SsidsEntry.java
42b74436Dk3WKJl6-SyP3LEBo3DXkQ tools/misc/policyprocessor/XmlToBin.java
42b74436ABj4SOVBWqY_IEIboFUkeA tools/misc/policyprocessor/XmlToBinInterface.java
42b7443684kBOrEBKFod4fGvnJ-rdA tools/misc/policyprocessor/myHandler.java
42b74436JjvZmOp2DfMb-TnpGZXQ8w tools/misc/policyprocessor/readme.install
42b74436-0Ig0yb-w1BYyCAFVTwqUg tools/misc/policyprocessor/readme.xen
42b74436WAJ6lmTO3foadk2527PFBQ tools/misc/policyprocessor/xen_sample_def.xml
42b744365VrTALmqRroQOBZ9EopUsw tools/misc/policyprocessor/xen_sample_policy.xml
42308df9dv_ZuP49nNPIROEMQ3F_LA tools/misc/xc_shadow.c
3f5ef5a2ir1kVAthS14Dc5QIRCEFWg tools/misc/xen-clone
3f5ef5a2dTZP0nnsFoeq2jRf3mWDDg tools/misc/xen-clone.README
@@ -785,6 +796,8 @@
41adc641dV-0cDLSyzMs5BT8nL7v3Q tools/misc/xenperf.c
4056f5155QYZdsk-1fLdjsZPFTnlhg tools/misc/xensymoops
40cf2937dqM1jWW87O5OoOYND8leuA tools/misc/xm
42b742f6JFcp6LFpYu-B4AEsfQwSFw tools/policy/Makefile
42b742f66XOdRMrwaHvbCdSSQyCrFw tools/policy/policy_tool.c
4270cc81g3nSNYCZ1ryCMDEbLtMtbQ tools/pygrub/Makefile
4270deeccyRsJn6jLnRh9odRtMW9SA tools/pygrub/README
4270cc81EIl7NyaS3Av6IPRk2c2a6Q tools/pygrub/setup.py
@@ -1101,6 +1114,12 @@
3f72f1bdJPsV3JCnBqs9ddL9tr6D2g xen/COPYING
3ddb79bcbOVHh38VJzc97-JEGD4dJQ xen/Makefile
3ddb79bcWnTwYsQRWl_PaneJfa6p0w xen/Rules.mk
42b742f6XHTfIEm_hUPtzjKr37LVhw xen/acm/Makefile
42b742f6tHzn0fZWH3TjPva8gbqpow xen/acm/acm_chinesewall_hooks.c
42b742f6bM8kZwuIUbepHZ8SQQkjJA xen/acm/acm_core.c
42b742f6cwfrPubqH47gQpke8xkYSA xen/acm/acm_null_hooks.c
42b742f69qSxm5MM-wtPaWtCqyI3KA xen/acm/acm_policy.c
42b742f6VbmdlwekQRMhXugjcu9QXg xen/acm/acm_simple_type_enforcement_hooks.c
421098b25A0RvuYN3rP28ga3_FN3_Q xen/arch/ia64/Makefile
421098b2okIeYXS9w9avmSozls61xA xen/arch/ia64/Rules.mk
421098b21p12UcKjHBrLh_LjlvNEwA xen/arch/ia64/acpi.c
@@ -1146,6 +1165,7 @@
425ae516juUB257qrwUdsL9AsswrqQ xen/arch/ia64/patch/linux-2.6.11/time.c
425ae5167zQn7zYcgKtDUDX2v-e8mw xen/arch/ia64/patch/linux-2.6.11/tlb.c
425ae5162bIl2Dgd19x-FceB4L9oGw xen/arch/ia64/patch/linux-2.6.11/types.h
42ae01f01KDfSgVQnscwJ0psRmEaCw xen/arch/ia64/patch/linux-2.6.11/uaccess.h
425ae516cFUNY2jHD46bujcF5NJheA xen/arch/ia64/patch/linux-2.6.11/unaligned.c
421098b39QFMC-1t1r38CA7NxAYBPA xen/arch/ia64/patch/linux-2.6.7/bootmem.h
421098b3SIA1vZX9fFUjo1T3o_jMCQ xen/arch/ia64/patch/linux-2.6.7/current.h
@@ -1323,6 +1343,7 @@
41a61536SZbR6cj1ukWTb0DYU-vz9w xen/common/multicall.c
3ddb79bdD4SLmmdMD7yLW5HcUWucXw xen/common/page_alloc.c
3e54c38dkHAev597bPr71-hGzTdocg xen/common/perfc.c
42b742f6mgq9puEr7lUrLST0VEpsig xen/common/policy_ops.c
40589968dD2D1aejwSOvrROg7fOvGQ xen/common/sched_bvt.c
41ebbfe9oF1BF3cH5v7yE3eOL9uPbA xen/common/sched_sedf.c
3e397e6619PgAfBbw2XFbXkewvUWgw xen/common/schedule.c
@@ -1338,6 +1359,9 @@
4049e6bfNSIq7s7OV-Bd69QD0RpR2Q xen/drivers/char/console.c
4298e018XQtZkCdufpyFimOGZqqsFA xen/drivers/char/ns16550.c
3e4a8cb7nMChlro4wvOBo76n__iCFA xen/drivers/char/serial.c
42b742f6OteAMPWnoqxqfRX3yxD0yw xen/include/acm/acm_core.h
42b742f6XfIijctEwA0YWL2BoWtDNg xen/include/acm/acm_endian.h
42b742f6jXvp1vdbU2v2WJjTPku65A xen/include/acm/acm_hooks.h
40715b2cFpte_UNWnBZW0Du7z9AhTQ xen/include/acpi/acconfig.h
40715b2ctNvVZ058w8eM8DR9hOat_A xen/include/acpi/acexcep.h
40715b2com8I01qcHcAw47e93XsCqQ xen/include/acpi/acglobal.h
@@ -1364,6 +1388,7 @@
421098b6ZcIrn_gdqjUtdJyCE0YkZQ xen/include/asm-ia64/debugger.h
421098b6z0zSuW1rcSJK1gR8RUi-fw xen/include/asm-ia64/dom_fw.h
421098b6Nn0I7hGB8Mkd1Cis0KMkhA xen/include/asm-ia64/domain.h
42b1d2d0rkNCmG2nFOnL-OfhJG9mDw xen/include/asm-ia64/event.h
4241e880hAyo_dk0PPDYj3LsMIvf-Q xen/include/asm-ia64/flushtlb.h
421098b6X3Fs2yht42TE2ufgKqt2Fw xen/include/asm-ia64/ia64_int.h
421098b7psFAn8kbeR-vcRCdc860Vw xen/include/asm-ia64/init.h
@@ -1388,7 +1413,6 @@
428b9f38is0zTsIm96_BKo4MLw0SzQ xen/include/asm-ia64/vmx_pal_vsa.h
428b9f38iDqbugHUheJrcTCD7zlb4g xen/include/asm-ia64/vmx_phy_mode.h
428b9f38grd_B0AGB1yp0Gi2befHaQ xen/include/asm-ia64/vmx_platform.h
428b9f38lm0ntDBusHggeQXkx1-1HQ xen/include/asm-ia64/vmx_ptrace.h
428b9f38XgwHchZEpOzRtWfz0agFNQ xen/include/asm-ia64/vmx_vcpu.h
428b9f38tDTTJbkoONcAB9ODP8CiVg xen/include/asm-ia64/vmx_vpd.h
428b9f38_o0U5uJqmxZf_bqi6_PqVw xen/include/asm-ia64/vtm.h
@@ -1412,6 +1436,7 @@
40715b2dTokMLYGSuD58BnxOqyWVew xen/include/asm-x86/div64.h
4204e7acwzqgXyTAPKa1nM-L7Ec0Qw xen/include/asm-x86/domain.h
41d3eaaeIBzW621S1oa0c2yk7X43qQ xen/include/asm-x86/e820.h
42b1d2caFkOByU5n4LuMnT05f3kJFg xen/include/asm-x86/event.h
3ddb79c3NU8Zy40OTrq3D-i30Y3t4A xen/include/asm-x86/fixmap.h
3e2d29944GI24gf7vOP_7x8EyuqxeA xen/include/asm-x86/flushtlb.h
4294b5eep4lWuDtYUR74gYwt-_FnHA xen/include/asm-x86/genapic.h
@@ -1487,6 +1512,8 @@
404f1bc4tWkB9Qr8RkKtZGW5eMQzhw xen/include/asm-x86/x86_64/uaccess.h
422f27c8RHFkePhD34VIEpMMqofZcA xen/include/asm-x86/x86_emulate.h
400304fcmRQmDdFYEzDh0wcBba9alg xen/include/public/COPYING
42b742f6duiOTlZvysQkRYZHYBXqvg xen/include/public/acm.h
42b742f7TIMsQgUaNDJXp3QlBve2SQ xen/include/public/acm_dom0_setup.h
421098b7OKb9YH_EUA_UpCxBjaqtgA xen/include/public/arch-ia64.h
404f1bc68SXxmv0zQpXBWGrCzSyp8w xen/include/public/arch-x86_32.h
404f1bc7IwU-qnH8mJeVu0YsNGMrcw xen/include/public/arch-x86_64.h
@@ -1500,8 +1527,10 @@
41d40e9b8zCk5VDqhVbuQyhc7G3lqA xen/include/public/io/ring.h
41ee5e8c6mLxIx82KPsbpt_uts_vSA xen/include/public/io/usbif.h
4051db79512nOCGweabrFWO2M2h5ng xen/include/public/physdev.h
42b742f7Lzy8SKKG25L_-fgk5FHA2Q xen/include/public/policy_ops.h
40589968wmhPmV5-ENbBYmMjnedgKw xen/include/public/sched_ctl.h
404f3d2eR2Owk-ZcGOx9ULGHg3nrww xen/include/public/trace.h
42b5a5f2QC1IxeuwCwwsOEhvcJ2BJg xen/include/public/version.h
4266bd01Ul-pC01ZVvBkhBnv5eqzvw xen/include/public/vmx_assist.h
3ddb79c25UE59iu4JJcbRalx95mvcg xen/include/public/xen.h
3e397e66m2tO3s-J8Jnr7Ws_tGoPTg xen/include/xen/ac_timer.h
+1
View File
@@ -39,6 +39,7 @@ iap10@labyrinth.cl.cam.ac.uk
iap10@nidd.cl.cam.ac.uk
iap10@pb001.cl.cam.ac.uk
iap10@pb007.cl.cam.ac.uk
iap10@spot.cl.cam.ac.uk
iap10@striker.cl.cam.ac.uk
iap10@tetris.cl.cam.ac.uk
jrb44@plym.cl.cam.ac.uk
+3
View File
@@ -31,3 +31,6 @@ endif
LDFLAGS += $(foreach i, $(EXTRA_LIB), -L$(i))
CFLAGS += $(foreach i, $(EXTRA_INCLUDES), -I$(i))
# Choose the best mirror to download linux kernel
KERNEL_REPO = http://www.kernel.org
+2 -1
View File
@@ -27,7 +27,7 @@ vpath linux-%.tar.bz2 $(LINUX_SRC_PATH)
linux-%.tar.bz2: override _LINUX_VDIR = $(word 1,$(subst ., ,$*)).$(word 2,$(subst ., ,$*))
linux-%.tar.bz2:
@echo "Cannot find $@ in path $(LINUX_SRC_PATH)"
wget http://www.kernel.org/pub/linux/kernel/v$(_LINUX_VDIR)/$@ -O./$@
wget $(KERNEL_REPO)/pub/linux/kernel/v$(_LINUX_VDIR)/$@ -O./$@
# Expand NetBSD release to NetBSD version
NETBSD_RELEASE ?= 2.0
@@ -57,6 +57,7 @@ $(patsubst %,pristine-%/.valid-pristine,$(ALLSPARSETREES)) : pristine-%/.valid-p
mkdir -p tmp-pristine-$*
touch tmp-pristine-$*/.bk_skip
tar -C tmp-pristine-$* -jxf $<
-@rm tmp-pristine-$*/pax_global_header
mv tmp-pristine-$*/* $(@D)
@rm -rf tmp-pristine-$*
touch $@ # update timestamp to avoid rebuild
+580
View File
@@ -0,0 +1,580 @@
Copyright: IBM Corporation (C)
20 June 2005
Author: Reiner Sailer
This document is a very short introduction into the sHype access control
security architecture implementation and how it is perceived by users. It
is a very preliminary draft for the courageous ones to get "their feet wet"
and to be able to give feedback (via the xen-devel/xense-devel mailing lists).
Install:
cd into xeno-unstable.bk
(use --dry-run option if you want to test the patch only)
patch -p1 -g0 < *tools.diff
patch -p1 -g0 < *xen.diff
(no rejects, probably some line offsets)
make uninstall; make mrproper; make; ./install.sh should install the default
sHype into Xen (rebuild your initrd images if necessary). Reboot.
Debug output: there are two triggers for debug output:
a) General sHype debug:
xeno-unstable.bk/xen/include/public/acm.h
undefine ACM_DEBUG to switch this debug off
b) sHype enforcement hook trace: This prints a small trace for each enforcement
hook that is executed. The trigger is in
xeno-unstable.bk/xen/include/acm/acm_hooks.h
undefine ACM_TRACE_MODE to switch this debug off
1. The default NULL policy
***************************
When you apply the patches and startup xen, you should at first not notice any
difference because the default policy is the "NULL" policy, which as the name
implies does not enforce anything.
However, when you try
[root@laptop policy]# xm list
Name Id Mem(MB) CPU State Time(s) Console SSID-REF
Domain-0 0 620 0 r---- 25.6 default
You might detect a new parameter "SSID-REF" displayed for domains. This
parameter describes the subject security identifier reference of the domain. It
is shown as "default" since there is no policy to be enforced.
To display the currently enforced policy, use the policy tool under xeno-
unstable.bk/tools/policy: policy_tool getpolicy. You should see output like the
one below.
[root@laptop policy]#./policy_tool getpolicy
Policy dump:
============
Magic = 1debc.
PolVer = aaaa0000.
Len = 14.
Primary = NULL policy (c=0, off=14).
Secondary = NULL policy (c=0, off=14).
No primary policy (NULL).
No secondary policy (NULL).
Policy dump End.
Since this is a dump of a binary policy, it's not pretty. The important parts
are the "Primary" and "Secondary" policy fields set to "NULL policy". sHype
currently allows to set two independent policies; thus the two SSID-REF parts
shown in 'xm list'. Right here: primary policy only means this policy is
checked first, the secondary policy is checked if the primary results in
"permitted access". The result of the combined policy is "permitted" if both
policies return permitted (NULL policy always returns permitted). The result is
"denied" if at least one of the policies returns "denied". Look into xeno-
unstable.bk/xen/include/acm/acm_hooks.h for the general hook structure
integrating the policy decisions (if you like, you won't need it for the rest
of the Readme file).
2. Setting Chinese Wall and Simple Type Enforcement policies:
*************************************************************
We'll get fast to the point. However, in order to understand what we are doing,
we must at least understand the purpose of the policies that we are going to
enforce. The two policies presented here are just examples and the
implementation encourages adding new policies easily.
2.1. Chinese Wall policy: "decides whether a domain can be started based on
this domain's ssidref and the ssidrefs of the currently running domains".
Generally, the Chinese wall policy allows specifying certain types (or classes
or categories, whatever the preferred word) that conflict; we usually assign a
type to a workload and the set of types of those workloads running in a domain
make up the type set for this domain. Each domain is assigned a set of types
through its SSID-REF (we register Chinese Wall as primary policy, so the
ssidref used for determining the Chinese Wall types is the one annotated with
"p:" in xm list) since each SSID-REF points at a set of types. We'll see how
SSIDREFs are represented in Xen later when we will look at the policy. (A good
read for Chinese Wall is: Brewer/Nash The Chinese Wall Security Policy 1989.)
So let's assume the Chinese Wall policy we are running distinguishes 10 types:
t0 ... t9. Let us assume further that each SSID-REF points to a set that
includes exactly one type (attached to domains that run workloads of a single
type). SSID-REF 0 points to {t0}, ssidref 1 points to {t1} ... 9 points to
{t9}. [This is actually the example policy we are going to push into xen later]
Now the Chinese Wall policy allows you to define "Conflict type sets" and it
guarantees that of any conflict set at most one type is "running" at any time.
As an example, we have defined 2 conflict set: {t2, t3} and {t0, t5, t6}.
Specifying these conflict sets, sHype ensures that at most one type of each set
is running (either t2 or t3 but not both; either t0 or t5 or t6 but not
multiple of them).
The effect is that administrators can define which workload types cannot run
simultaneously on a single Xen system. This is useful to limit the covert
timing channels between such payloads or to ensure that payloads don't
interfere with each other through existing resource dependencies.
2.2. Simple Type Enforcement (ste) policy: "decides whether two domains can
share data, e.g., setup event channels or grant tables to each other, based on
the two domains' ssidref. This, as the name says, is a simple policy. Think of
each type as of a single color. Each domain has one or more colors, i.e., the
domains ssid for the ste policy points to a set that has set one or multiple
types. Let us assume in our example policy we differentiate 5 colors (types)
and define 5 different ssids referenced by ssidref=0..4. Each ssid shall have
exactly one type set, i.e., describes a uni-color. Only ssid(0) has all types
set, i.e., has all defined colors.
Sharing is enforced by the ste policy by requiring that two domains that want
to establish an event channel or grant pages to each other must have a common
color. Currently all domains communicate through DOM0 by default; i.e., Domain0
will necessarily have all colors to be able to create domains (thus, we will
assign ssidref(0) to Domain0 in our example below.
More complex mandatory access control policies governing sharing will follow;
such policies are more sophisticated than the "color" scheme above by allowing
more flexible (and complex :_) access control decisions than "share a color" or
"don't share a color" and will be able to express finer-grained policies.
2.3 Binary Policy:
In the future, we will have a policy tool that takes as input a more humane
policy description, using types such as development, home-banking, donated-
Grid, CorpA-Payload ... and translates the respective policy into what we see
today as the binary policy using 1s and 0s and sets of them. For now, we must
live with the binary policy when working with sHype.
2.4 Exemplary use of a real sHype policy on Xen. To activate a real policy,
edit the file (yes, this will soon be a compile option):
xeno-unstable.bk/xen/include/public/acm.h
Change: #define ACM_USE_SECURITY_POLICY ACM_NULL_POLICY
To : #define ACM_USE_SECURITY_POLICY ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY
cd xeno-unstable.bk
make mrproper
make uninstall (manually remove /etc/xen.old if necessary)
make
./install.sh (recreate your kernel initrd's if necessary)
Reboot into new xen.gz
After booting, check out 'xm dmesg'; should show somewhere in the middle:
(XEN) acm_init: Enforcing Primary CHINESE WALL policy, Secondary SIMPLE TYPE
ENFORCEMENT policy.
Even though you can activate those policies in any combination and also
independently, the policy tool currently only supports setting the policy for
the above combination.
Now look at the minimal startup policy with:
xeno-unstable.bk/tools/policytool getpolicy
You should see something like:
[root@laptop policy]# ./policy_tool getpolicy
Policy dump:
============
Magic = 1debc.
PolVer = aaaa0000.
Len = 36.
Primary = CHINESE WALL policy (c=1, off=14).
Secondary = SIMPLE TYPE ENFORCEMENT policy (c=2, off=2c).
Chinese Wall policy:
====================
Max Types = 1.
Max Ssidrefs = 1.
Max ConfSets = 1.
Ssidrefs Off = 10.
Conflicts Off = 12.
Runing T. Off = 14.
C. Agg. Off = 16.
SSID To CHWALL-Type matrix:
ssidref 0: 00
Confict Sets:
c-set 0: 00
Running
Types: 00
Conflict
Aggregate Set: 00
Simple Type Enforcement policy:
===============================
Max Types = 1.
Max Ssidrefs = 1.
Ssidrefs Off = 8.
SSID To STE-Type matrix:
ssidref 0: 01
Policy dump End.
This is a minimal policy (of little use), except it will disable starting any
domain that does not have ssidref set to 0x0. The Chinese Wall policy has
nothing to enforce and the ste policy only knows one type, which is set for the
only defined ssidref.
The item that defines the ssidref in a domain configuration is:
ssidref = 0x12345678
Where ssidref is interpreted as a 32bit number, where the lower 16bits become
the ssidref for the primary policy and the higher 16bits become the ssidref for
the secondary policy. sHype currently supports two policies but this is an
implementation decision and can be extended if necessary.
This reference defines the security information of a domain. The meaning of the
SSID-REF depends on the policy, so we explain it when we explain the real
policies.
Setting a new Security Policy:
******************************
The policy tool with all its current limitations has one usable example policy
compiled-in. Please try at this time to use the setpolicy command:
xeno-unstable.bk/tools/policy/policy_tool setpolicy
You should see a dump of the policy you are setting. It should say at the very
end:
Policy successfully set.
Now try to dump the currently enforced policy, which is the policy we have just
set and the dynamic security state information of this policy
(<<< ... some additional explanations)
[root@laptop policy]# ./policy_tool getpolicy
Policy dump:
============
Magic = 1debc.
PolVer = aaaa0000.
Len = 112.
Primary = CHINESE WALL policy (c=1, off=14).
Secondary = SIMPLE TYPE ENFORCEMENT policy (c=2, off=d8).
Chinese Wall policy:
====================
Max Types = a.
Max Ssidrefs = 5.
Max ConfSets = 2.
Ssidrefs Off = 10.
Conflicts Off = 74.
Runing T. Off = 9c.
C. Agg. Off = b0.
SSID To CHWALL-Type matrix:
ssidref 0: 01 00 00 00 00 00 00 00 00 00 <<< type0 is set for ssidref0
ssidref 1: 00 01 00 00 00 00 00 00 00 00
ssidref 2: 00 00 01 00 00 00 00 00 00 00
ssidref 3: 00 00 00 01 00 00 00 00 00 00
ssidref 4: 00 00 00 00 01 00 00 00 00 00 <<< type4 is set for ssidref4
<<< types 5-9 are unused
Confict Sets:
c-set 0: 00 00 01 01 00 00 00 00 00 00 <<< type2 and type3 never run together
c-set 1: 01 00 00 00 00 01 01 00 00 00 <<< only one of types 0, 5 or 6
<<< can run simultaneously
Running
Types: 01 00 00 00 00 00 00 00 00 00 <<< ref-count for types of running domains
Conflict
Aggregate Set: 00 00 00 00 00 01 01 00 00 00 <<< aggregated set of types that
<<< cannot run because they
<<< are in conflict set 1 and
<<< (domain 0 is running w t0)
Simple Type Enforcement policy:
===============================
Max Types = 5.
Max Ssidrefs = 5.
Ssidrefs Off = 8.
SSID To STE-Type matrix:
ssidref 0: 01 01 01 01 01 <<< ssidref0 points to a set that
<<< has all types set (colors)
ssidref 1: 00 01 00 00 00 <<< ssidref1 has color1 set
ssidref 2: 00 00 01 00 00 <<< ...
ssidref 3: 00 00 00 01 00
ssidref 4: 00 00 00 00 01
Policy dump End.
This is a small example policy with which we will demonstrate the enforcement.
Starting Domains with policy enforcement
========================================
Now let us play with this policy.
Define 3 or 4 domain configurations. I use the following config using a ramdisk
only and about 8MBytes of memory for each DomU (test purposes):
#-------configuration xmsec1-------------------------
kernel = "/boot/vmlinuz-2.6.11-xenU"
ramdisk="/boot/U1_ramdisk.img"
#security reference identifier
ssidref= 0x00010001
memory = 10
name = "xmsec1"
cpu = -1 # leave to Xen to pick
# Number of network interfaces. Default is 1.
nics=1
dhcp="dhcp"
#-----------------------------------------------------
xmsec2 and xmsec3 look the same except for the name and the ssidref line. Use
your domain config file and add "ssidref = 0x00010001" to the first (xmsec1),
"ssidref= 0x00020002" to the second (call it xmsec2), and "ssidref=0x00030003"
to the third (we will call this one xmsec3).
First start xmsec1: xm create -c xmsec1 (succeeds)
Then
[root@laptop policy]# xm list
Name Id Mem(MB) CPU State Time(s) Console SSID-REF
Domain-0 0 620 0 r---- 42.3 s:00/p:00
xmnosec 1 9 0 -b--- 0.3 9601 s:00/p:05
xmsec1 2 9 0 -b--- 0.2 9602 s:01/p:01
Shows a new domain xmsec1 running with primary (here: chinese wall) ssidref 1
and secondary (here: simple type enforcement) ssidref 1. The ssidrefs are
independent and can differ for a domain.
[root@laptop policy]# ./policy_tool getpolicy
Policy dump:
============
Magic = 1debc.
PolVer = aaaa0000.
Len = 112.
Primary = CHINESE WALL policy (c=1, off=14).
Secondary = SIMPLE TYPE ENFORCEMENT policy (c=2, off=d8).
Chinese Wall policy:
====================
Max Types = a.
Max Ssidrefs = 5.
Max ConfSets = 2.
Ssidrefs Off = 10.
Conflicts Off = 74.
Runing T. Off = 9c.
C. Agg. Off = b0.
SSID To CHWALL-Type matrix:
ssidref 0: 01 00 00 00 00 00 00 00 00 00
ssidref 1: 00 01 00 00 00 00 00 00 00 00
ssidref 2: 00 00 01 00 00 00 00 00 00 00
ssidref 3: 00 00 00 01 00 00 00 00 00 00
ssidref 4: 00 00 00 00 01 00 00 00 00 00
Confict Sets:
c-set 0: 00 00 01 01 00 00 00 00 00 00
c-set 1: 01 00 00 00 00 01 01 00 00 00 <<< t1 is not part of any c-set
Running
Types: 01 01 00 00 00 00 00 00 00 00 <<< xmsec1 has ssidref 1->type1
^^ <<< ref-count at position 1 incr
Conflict
Aggregate Set: 00 00 00 00 00 01 01 00 00 00 <<< domain 1 was allowed to
<<< start since type 1 was not
<<< in conflict with running
<<< types
Simple Type Enforcement policy:
===============================
Max Types = 5.
Max Ssidrefs = 5.
Ssidrefs Off = 8.
SSID To STE-Type matrix:
ssidref 0: 01 01 01 01 01 <<< the ste policy does not maintain; we
ssidref 1: 00 01 00 00 00 <-- <<< see that domain xmsec1 has ste
ssidref 2: 00 00 01 00 00 <<< ssidref1->type1 and has this type in
ssidref 3: 00 00 00 01 00 <<< common with dom0
ssidref 4: 00 00 00 00 01
Policy dump End.
Look at sHype output in xen dmesg:
[root@laptop xen]# xm dmesg
.
.
[somewhere near the very end]
(XEN) chwall_init_domain_ssid: determined chwall_ssidref to 1.
(XEN) ste_init_domain_ssid.
(XEN) ste_init_domain_ssid: determined ste_ssidref to 1.
(XEN) acm_init_domain_ssid: Instantiated individual ssid for domain 0x01.
(XEN) chwall_post_domain_create.
(XEN) ste_pre_eventchannel_interdomain.
(XEN) ste_pre_eventchannel_interdomain: (evtchn 0 --> 1) common type #01.
(XEN) shype_authorize_domops.
(XEN) ste_pre_eventchannel_interdomain.
(XEN) ste_pre_eventchannel_interdomain: (evtchn 0 --> 1) common type #01.
(XEN) ste_pre_eventchannel_interdomain.
(XEN) ste_pre_eventchannel_interdomain: (evtchn 0 --> 1) common type #01.
You can see that the chinese wall policy does not complain and that the ste
policy makes three access control decisions for three event-channels setup
between domain 0 and the new domain 1. Each time, the two domains share the
type1 and setting up the eventchannel is permitted.
Starting up a second domain xmsec2:
[root@laptop xen]# xm create -c xmsec2
Using config file "xmsec2".
Started domain xmsec2, console on port 9602
************ REMOTE CONSOLE: CTRL-] TO QUIT ********
Linux version 2.6.11-xenU (root@laptop.home.org) (gcc version 3.4.2 20041017
(Red Hat 3.4.2-6.fc3)) #1 Wed Mar 30 13:14:31 EST 2005
.
.
.
[root@laptop policy]# xm list
Name Id Mem(MB) CPU State Time(s) Console SSID-REF
Domain-0 0 620 0 r---- 71.7 s:00/p:00
xmsec1 1 9 0 -b--- 0.3 9601 s:01/p:01
xmsec2 2 7 0 -b--- 0.3 9602 s:02/p:02 << our domain runs both policies with ssidref 2
[root@laptop policy]# ./policy_tool getpolicy
Policy dump:
============
Magic = 1debc.
PolVer = aaaa0000.
Len = 112.
Primary = CHINESE WALL policy (c=1, off=14).
Secondary = SIMPLE TYPE ENFORCEMENT policy (c=2, off=d8).
Chinese Wall policy:
====================
Max Types = a.
Max Ssidrefs = 5.
Max ConfSets = 2.
Ssidrefs Off = 10.
Conflicts Off = 74.
Runing T. Off = 9c.
C. Agg. Off = b0.
SSID To CHWALL-Type matrix:
ssidref 0: 01 00 00 00 00 00 00 00 00 00
ssidref 1: 00 01 00 00 00 00 00 00 00 00
ssidref 2: 00 00 01 00 00 00 00 00 00 00 <<< our domain has type 2 set
ssidref 3: 00 00 00 01 00 00 00 00 00 00
ssidref 4: 00 00 00 00 01 00 00 00 00 00
Confict Sets:
c-set 0: 00 00 01 01 00 00 00 00 00 00 <<< t2 is in c-set0 with type 3
c-set 1: 01 00 00 00 00 01 01 00 00 00
Running
Types: 01 01 01 00 00 00 00 00 00 00 <<< t2 is running since the
^^ <<< current aggregate conflict
<<< set (see above) does not
<<< include type 2
Conflict
Aggregate Set: 00 00 00 01 00 01 01 00 00 00 <<< type 3 is added to the
<<< conflict aggregate
Simple Type Enforcement policy:
===============================
Max Types = 5.
Max Ssidrefs = 5.
Ssidrefs Off = 8.
SSID To STE-Type matrix:
ssidref 0: 01 01 01 01 01
ssidref 1: 00 01 00 00 00
ssidref 2: 00 00 01 00 00
ssidref 3: 00 00 00 01 00
ssidref 4: 00 00 00 00 01
Policy dump End.
The sHype xen dmesg output looks similar to the one above when starting the
first domain.
Now we start xmsec3 and it has ssidref3. Thus, it tries to run as type3 which
conflicts with running type2 (from xmsec2). As expected, creating this domain
fails for security policy enforcement reasons.
[root@laptop xen]# xm create -c xmsec3
Using config file "xmsec3".
Error: Error creating domain: (22, 'Invalid argument')
[root@laptop xen]#
[root@laptop xen]# xm dmesg
.
.
[somewhere near the very end]
(XEN) chwall_pre_domain_create.
(XEN) chwall_pre_domain_create: CHINESE WALL CONFLICT in type 03.
xmsec3 ssidref3 points to type3, which is in the current conflict aggregate
set. This domain cannot start until domain xmsec2 is destroyed, at which time
the aggregate conflict set is reduced and type3 is excluded from it. Then,
xmsec3 can start. Of course, afterwards, xmsec2 cannot be restarted. Try it.
3. Policy tool
**************
toos/policy/policy_tool.c
a) ./policy_tool getpolicy
prints the currently enforced policy
(see for example section 1.)
b) ./policy_tool setpolicy
sets a predefined and hardcoded security
policy (the one described in section 2.)
c) ./policy_tool dumpstats
prints some status information about the caching
of access control decisions (number of cache hits
and number of policy evaluations for grant_table
and event channels).
d) ./policy_tool loadpolicy <binary_policy_file>
sets the policy defined in the <binary_policy_file>
please use the policy_processor that is posted to this
mailing list to create such a binary policy from an XML
policy description
4. Policy interface:
********************
The Policy interface is working in "network-byte-order" (big endian). The reason for this
is that policy files/management should be portable and independent of the platforms.
Our policy interface enables managers to create a single binary policy file in a trusted
environment and distributed it to multiple systems for enforcement.
====================end-of file=======================================
@@ -623,7 +623,7 @@ static int netif_poll(struct net_device *dev, int *pbudget)
/* Only copy the packet if it fits in the current MTU. */
if (skb->len <= (dev->mtu + ETH_HLEN)) {
if ((skb->tail > skb->end) && net_ratelimit())
printk(KERN_INFO "Received packet needs %d bytes more "
printk(KERN_INFO "Received packet needs %zd bytes more "
"headroom.\n", skb->tail - skb->end);
if ((nskb = alloc_xen_skb(skb->len + 2)) != NULL) {
@@ -967,9 +967,9 @@ static int create_netdev(int handle, struct net_device **val)
/* Initialise {tx,rx}_skbs to be a free chain containing every entry. */
for (i = 0; i <= NETIF_TX_RING_SIZE; i++)
np->tx_skbs[i] = (void *)(i+1);
np->tx_skbs[i] = (void *)((unsigned long) i+1);
for (i = 0; i <= NETIF_RX_RING_SIZE; i++)
np->rx_skbs[i] = (void *)(i+1);
np->rx_skbs[i] = (void *)((unsigned long) i+1);
dev->open = network_open;
dev->hard_start_xmit = network_start_xmit;
@@ -1343,7 +1343,7 @@ static int xennet_proc_read(
{
struct net_device *dev = (struct net_device *)((unsigned long)data & ~3UL);
struct net_private *np = netdev_priv(dev);
int len = 0, which_target = (int)data & 3;
int len = 0, which_target = (unsigned long) data & 3;
switch (which_target)
{
@@ -1368,7 +1368,7 @@ static int xennet_proc_write(
{
struct net_device *dev = (struct net_device *)((unsigned long)data & ~3UL);
struct net_private *np = netdev_priv(dev);
int which_target = (int)data & 3;
int which_target = (unsigned long) data & 3;
char string[64];
long target;
+1
View File
@@ -12,6 +12,7 @@ SUBDIRS += xcs
SUBDIRS += xcutils
SUBDIRS += pygrub
SUBDIRS += firmware
SUBDIRS += policy
.PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean
+2
View File
@@ -110,6 +110,7 @@ int xc_waitdomain_core(int domain,
typedef struct {
u32 domid;
u32 ssidref;
unsigned int dying:1, crashed:1, shutdown:1,
paused:1, blocked:1, running:1;
unsigned int shutdown_reason; /* only meaningful if shutdown==1 */
@@ -124,6 +125,7 @@ typedef struct {
typedef dom0_getdomaininfo_t xc_domaininfo_t;
int xc_domain_create(int xc_handle,
u32 ssidref,
u32 *pdomid);
+3
View File
@@ -9,6 +9,7 @@
#include "xc_private.h"
int xc_domain_create(int xc_handle,
u32 ssidref,
u32 *pdomid)
{
int err;
@@ -16,6 +17,7 @@ int xc_domain_create(int xc_handle,
op.cmd = DOM0_CREATEDOMAIN;
op.u.createdomain.domain = (domid_t)*pdomid;
op.u.createdomain.ssidref = ssidref;
if ( (err = do_dom0_op(xc_handle, &op)) != 0 )
return err;
@@ -101,6 +103,7 @@ int xc_domain_getinfo(int xc_handle,
info->crashed = 1;
}
info->ssidref = op.u.getdomaininfo.ssidref;
info->nr_pages = op.u.getdomaininfo.tot_pages;
info->max_memkb = op.u.getdomaininfo.max_pages<<(PAGE_SHIFT);
info->shared_info_frame = op.u.getdomaininfo.shared_info_frame;
@@ -0,0 +1,34 @@
/**
* (C) Copyright IBM Corp. 2005
*
* $Id: SecurityLabel.java,v 1.2 2005/06/17 20:00:04 rvaldez Exp $
*
* Author: Ray Valdez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*
* SecurityLabel Class.
*
* <p>
*
* Keeps track of types.
*
* <p>
*
*
*/
import java.util.*;
public class SecurityLabel
{
Vector ids;
Vector vlans;
Vector slots;
Vector steTypes;
int steSsidPosition;
Vector chwIDs;
Vector chwTypes;
int chwSsidPosition;
}
@@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Author: Ray Valdez, rvaldez@us.ibm.com -->
<!-- xml schema definition for xen xml policies -->
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.ibm.com"
xmlns="http://www.ibm.com"
elementFormDefault="qualified">
<xsd:element name="TE" type="xsd:string" />
<xsd:element name="ChWall" type="xsd:string" />
<xsd:element name="Definition">
<xsd:complexType>
<xsd:sequence>
<!-- simple type enforcement -->
<xsd:element name="Types" minOccurs ="0" maxOccurs="1">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="TE" minOccurs ="1" maxOccurs ="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<!-- chinese wall -->
<!-- type definition -->
<xsd:element name="ChWallTypes" minOccurs ="0" maxOccurs="1">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="ChWall" minOccurs ="1" maxOccurs ="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<!-- conflict set -->
<xsd:element name="ConflictSet" minOccurs ="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="ChWall" minOccurs ="2" maxOccurs ="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="Policy">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="PolicyHeader">
<xsd:complexType>
<xsd:all>
<xsd:element name = "Name" type="xsd:string"/>
<xsd:element name = "DateTime" type="xsd:dateTime"/>
<xsd:element name = "Tag" minOccurs ="1" maxOccurs ="1" type="xsd:string"/>
<xsd:element name = "TypeDefinition">
<xsd:complexType>
<xsd:all>
<xsd:element name = "url" type="xsd:string"/>
<xsd:element name = "hash" minOccurs ="0" maxOccurs ="1" type="xsd:string"/>
</xsd:all>
</xsd:complexType>
</xsd:element>
</xsd:all>
</xsd:complexType>
</xsd:element>
<xsd:element name="VM" minOccurs ="1" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="id" type="xsd:integer"/>
<xsd:element ref="TE" minOccurs="0" maxOccurs="unbounded" />
<xsd:element ref="ChWall" minOccurs ="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="Vlan" minOccurs ="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="vid" type="xsd:integer"/>
<xsd:element ref="TE" minOccurs="1" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="Slot" minOccurs ="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="bus" type="xsd:integer"/>
<xsd:element name="slot" type="xsd:integer"/>
<xsd:element ref="TE" minOccurs="1" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<!-- root element -->
<xsd:element name="SecurityPolicySpec">
<xsd:complexType>
<xsd:choice>
<xsd:element ref="Definition" minOccurs ="1" maxOccurs="unbounded"/>
<xsd:element ref="Policy" minOccurs ="1" maxOccurs="unbounded"/>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
@@ -0,0 +1,29 @@
/**
* (C) Copyright IBM Corp. 2005
*
* $Id: SsidsEntry.java,v 1.2 2005/06/17 20:02:40 rvaldez Exp $
*
* Author: Ray Valdez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*
* SsidsEntry Class.
* <p>
*
* Holds ssid information.
*
* <p>
*
*
*/
public class SsidsEntry
{
int id; /* used for partition and vlan */
int bus; /* used for slots */
int slot;
int ste = 0xffffffff;
int chw = 0xffffffff;
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,135 @@
/**
* (C) Copyright IBM Corp. 2005
*
* $Id: XmlToBinInterface.java,v 1.2 2005/06/17 20:00:04 rvaldez Exp $
*
* Author: Ray Valdez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*
* XmlToBinInterface Class.
* <p>
*
* Defines constants used by XmToBin.
*
* <p>
*
* policy binary structures
*
* typedef struct {
* u32 magic;
*
* u32 policyversion;
* u32 len;
*
* u16 primary_policy_code;
* u16 primary_buffer_offset;
* u16 secondary_policy_code;
* u16 secondary_buffer_offset;
* u16 resource_offset;
*
* } acm_policy_buffer_t;
*
* typedef struct {
* u16 policy_code;
* u16 ste_max_types;
* u16 ste_max_ssidrefs;
* u16 ste_ssid_offset;
* } acm_ste_policy_buffer_t;
*
* typedef struct {
* uint16 policy_code;
* uint16 chwall_max_types;
* uint16 chwall_max_ssidrefs;
* uint16 chwall_max_conflictsets;
* uint16 chwall_ssid_offset;
* uint16 chwall_conflict_sets_offset;
* uint16 chwall_running_types_offset;
* uint16 chwall_conflict_aggregate_offset;
* } acm_chwall_policy_buffer_t;
*
* typedef struct {
* u16 partition_max;
* u16 partition_offset;
* u16 vlan_max;
* u16 vlan_offset;
* u16 slot_max;
* u16 slot_offset;
* } acm_resource_buffer_t;
*
* typedef struct {
* u16 id;
* u16 ssid_ste;
* u16 ssid_chwall;
* } acm_partition_entry_t;
*
* typedef struct {
* u16 vlan;
* u16 ssid_ste;
* } acm_vlan_entry_t;
*
* typedef struct {
* u16 bus;
* u16 slot;
* u16 ssid_ste;
* } acm_slot_entry_t;
*
*
*
*/
public interface XmlToBinInterface
{
/* policy code (uint16) */
final int policyCodeSize = 2;
/* max_types (uint16) */
final int maxTypesSize = 2;
/* max_ssidrefs (uint16) */
final int maxSsidrefSize = 2;
/* ssid_offset (uint32) */
final int ssidOffsetSize = 2;
final short markSymbol = 0x0001;
final int u32Size = 4;
final int u16Size = 2;
/* num of bytes for acm_ste_policy_buffer_t */
final short steHeaderSize = (4 * u16Size);
/* byte for acm_chinese_wall_policy_buffer_t */
final short chwHeaderSize = (8 * u16Size);
final short primaryPolicyCodeSize = u16Size;
final short primaryBufferOffsetSize = u16Size ;
final int secondaryPolicyCodeSz = u16Size;
final int secondaryBufferOffsetSz = u16Size;
final short resourceOffsetSz = u16Size;
final short partitionBufferSz = (2 * u16Size);
final short partitionEntrySz = (3 * u16Size);
final short slotBufferSz = (2 * u16Size);
final short slotEntrySz = (3 * u16Size);
final short vlanBufferSz = (2 * u16Size);
final short vlanEntrySz = (2 * u16Size);
final short binaryBufferHeaderSz = (3 * u32Size + 4* u16Size);
/* copied directlty from policy_ops.h */
final int POLICY_INTERFACE_VERSION = 0xAAAA0000;
/* copied directly from acm.h */
final int ACM_MAGIC = 0x0001debc;
final short ACM_NULL_POLICY = 0;
final short ACM_CHINESE_WALL_POLICY = 1;
final short ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY = 2;
final short ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY = 3;
final short ACM_EMPTY_POLICY = 4;
}
+47
View File
@@ -0,0 +1,47 @@
/**
* (C) Copyright IBM Corp. 2005
*
* $Id: myHandler.java,v 1.2 2005/06/17 20:00:04 rvaldez Exp $
*
* Author: Ray Valdez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*
* myHandler Class.
*
* <p>
*
* A dummy class used for detecting XML validating/parsing errors.
*
* <p>
*
*
*/
import org.xml.sax.helpers.*;
import org.xml.sax.SAXParseException;
class myHandler extends DefaultHandler
{
public boolean isValid = true;
/* Notification of a recoverable error. */
public void error(SAXParseException se)
{
isValid = false;
}
/* Notification of a non-recoverable error. */
public void fatalError(SAXParseException se)
{
isValid = false;
}
/* Notification of a warning. */
public void warning(SAXParseException se)
{
isValid = false;
}
}
+33
View File
@@ -0,0 +1,33 @@
# Author: Ray Valdez, rvaldez@us.ibm.com
# Version: 1.0
#
# install readme
#
PREREQUISITES:
Prior to installation of the policy processor tool (XmlToBin) you must have...
1. Java version 1.4.2
2. xmlParserAPIs.jar and xercesImpl.jar
The above can be obtained from the Sun Developer Network web site at
http://java.sun.com/j2se/1.4.2/download.html.
XmlParserAPIs and xercesImpl jars can be obtained from
http://www.apache.org/dist/xml/xerces-j (Xerces-J-bin.2.6.2.tar.gz,
for example).
The tool has been tested with J2SE v1.4.2_08 JRE on Linux (32-bit
INTEL).
INSTALLATION
1. Set PATH to include $HOME_JAVA/bin and $HOME_JAVA/jre/bin
where $HOME_JAVA is your java installation directory
2. Compile XmlToBin:
javac XmlToBin.java
USAGE
See readme.xen
+65
View File
@@ -0,0 +1,65 @@
# Author: Ray Valdez, rvaldez@us.ibm.com
# Version: 1.0
#
# This readme describes the policy processor tool for sHype.
#
Java program:
java XmlToBin -i [file.xml] -o <file.bin> -xssid <SsidFile> -xssidconf <SsidConf>
Command line options:
-i inputFile: name of policyfile (.xml)
-o outputFile: name of binary policy file (Big Endian)
-xssid SsidFile: xen ssids to named types text file
-xssidconf SsidConf: xen conflict ssids to types text file
-debug turn on debug messages
-help help. This printout
Where:
file.xml is the (input) xml policy file to be parsed and validated.
The syntax for file.xml is defined in the SecurityPolicySpec.xsd file.
file.bin is the (output) binary policy file generated by XmlToBin.
This binary policy can be activated in sHype. The binary policy file
is laid out in network byte order (i.e., big endian). The SsidFile
file contains the mapping of type enforcement (TE) ssids to the "named
types". Similarly, the SsidConf file contains the mapping of Chinese
Wall (ChWall) ssids to conflict named types. The ssidFile and SsidConf
files are used by Xen.
Xml Schema and policy:
The SecurityPolicySpec.xsd defines the syntax of a policy file. It
declares the tags that are used by XmlToBin to generate the binary
policy file. The tags that XmlToBin keys on are TE, ChWall, id, vid,
etc. The xml files that describe a policy are simple. Semantic
checking of a policy is performed mostly by XmlToBin. A type, for
example, is a string. No fixed values are defined for types in Xml.
A policy consists of two Xml files: definition and policy. The
definition Xml declares the types that are permitted in the policy
Xml. The policy Xml contains the assignment of labels to
subject/object (e.g., vm). This Xml file contains an explicit
reference to the definition Xml (e.g., <url>xen_sample_def.xml</url>).
The policy Xml is the one provided as a command line argument.
Files:
*.java - policy processor source
xen_sample_policy.xml - sample xml policy file
xen_sample_def.xml - sample user defined types
SecurityPolicySpec.xsd - schema definition file
To generate the sample binary policy:
export CLASSPATH=$XERCES_HOME/xercesImpl.jar:$XERCES_HOME/xmlParserAPIs.jar:.
java XmlToBin -i xen_sample_policy.xml -o xen_sample_policy.bin
where $XERCES_HOME is the installation directory of the Apache Xerces-J
@@ -0,0 +1,46 @@
<?xml version="1.0"?>
<!-- Author: Ray Valdez, rvaldez@us.ibm.com -->
<!-- example policy type definition -->
<SecurityPolicySpec
xmlns="http://www.ibm.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.ibm.com SecurityPolicySpec.xsd">
<Definition>
<!-- an example of a simple type enforcement type definition -->
<Types>
<TE>LOCAL-management</TE>
<TE>R-Company-development</TE>
<TE>S-Company-order</TE>
<TE>T-Company-advertising</TE>
<TE>U-Company-computing</TE>
<!-- TE nondevelopment -->
</Types>
<!-- an example of a chinese wall type definition along with conflict sets-->
<ChWallTypes>
<ChWall>Q-Company</ChWall>
<ChWall>R-Company</ChWall>
<ChWall>S-Company</ChWall>
<ChWall>T-Company</ChWall>
<ChWall>U-Company</ChWall>
<ChWall>V-Company</ChWall>
<ChWall>W-Company</ChWall>
<ChWall>X-Company</ChWall>
<ChWall>Y-Company</ChWall>
<ChWall>Z-Company</ChWall>
</ChWallTypes>
<ConflictSet>
<ChWall>T-Company</ChWall>
<ChWall>S-Company</ChWall>
</ConflictSet>
<ConflictSet>
<ChWall>Q-Company</ChWall>
<ChWall>V-Company</ChWall>
<ChWall>W-Company</ChWall>
</ConflictSet>
</Definition>
</SecurityPolicySpec>
@@ -0,0 +1,58 @@
<?xml version="1.0"?>
<!-- Author: Ray Valdez, rvaldez@us.ibm.com -->
<!-- example xen policy file -->
<SecurityPolicySpec
xmlns="http://www.ibm.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.ibm.com SecurityPolicySpec.xsd">
<Policy>
<PolicyHeader>
<Name>xen sample policy</Name>
<DateTime>2005-05-20T16:56:00</DateTime>
<Tag>foobar</Tag>
<TypeDefinition>
<url>xen_sample_def.xml</url>
<hash>abcdef123456abcdef</hash>
</TypeDefinition>
</PolicyHeader>
<VM>
<id> 0 </id>
<TE>LOCAL-management</TE>
<TE>R-Company-development</TE>
<TE>S-Company-order</TE>
<TE>T-Company-advertising</TE>
<TE>U-Company-computing</TE>
<ChWall>Q-Company</ChWall>
</VM>
<VM>
<id> 1 </id>
<TE>R-Company-development</TE>
<ChWall>R-Company</ChWall>
</VM>
<VM>
<id> 2 </id>
<TE>S-Company-order</TE>
<ChWall>S-Company</ChWall>
</VM>
<VM>
<id> 3 </id>
<TE>T-Company-advertising</TE>
<ChWall>T-Company</ChWall>
</VM>
<VM>
<id> 4 </id>
<TE>U-Company-computing</TE>
<ChWall>U-Company</ChWall>
</VM>
</Policy>
</SecurityPolicySpec>
+36
View File
@@ -0,0 +1,36 @@
XEN_ROOT = ../..
include $(XEN_ROOT)/tools/Rules.mk
SRCS = policy_tool.c
CFLAGS += -static
CFLAGS += -Wall
CFLAGS += -Werror
CFLAGS += -O3
CFLAGS += -fno-strict-aliasing
CFLAGS += -I.
all: build
build: mk-symlinks
$(MAKE) policy_tool
default: all
install: all
policy_tool : policy_tool.c
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $<
clean:
rm -rf policy_tool xen
LINUX_ROOT := $(wildcard $(XEN_ROOT)/linux-2.6.*-xen-sparse)
mk-symlinks:
[ -e xen/linux ] || mkdir -p xen/linux
[ -e xen/io ] || mkdir -p xen/io
( cd xen >/dev/null ; \
ln -sf ../$(XEN_ROOT)/xen/include/public/*.h . )
( cd xen/io >/dev/null ; \
ln -sf ../../$(XEN_ROOT)/xen/include/public/io/*.h . )
( cd xen/linux >/dev/null ; \
ln -sf ../../$(LINUX_ROOT)/include/asm-xen/linux-public/*.h . )
+557
View File
@@ -0,0 +1,557 @@
/****************************************************************
* policy_tool.c
*
* Copyright (C) 2005 IBM Corporation
*
* Authors:
* Reiner Sailer <sailer@watson.ibm.com>
* Stefan Berger <stefanb@watson.ibm.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*
* sHype policy management tool. This code runs in a domain and
* manages the Xen security policy by interacting with the
* Xen access control module via a /proc/xen/policycmd proc-ioctl,
* which is translated into a policy_op hypercall into Xen.
*
* todo: implement setpolicy to dynamically set a policy cache.
*/
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <string.h>
#include <stdint.h>
#include <netinet/in.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
#include <xen/acm.h>
#include <xen/policy_ops.h>
#include <xen/linux/privcmd.h>
#define ERROR(_m, _a...) \
fprintf(stderr, "ERROR: " _m "\n" , ## _a )
#define PERROR(_m, _a...) \
fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
errno, strerror(errno))
static inline int do_policycmd(int xc_handle,
unsigned int cmd,
unsigned long data)
{
return ioctl(xc_handle, cmd, data);
}
static inline int do_xen_hypercall(int xc_handle,
privcmd_hypercall_t *hypercall)
{
return do_policycmd(xc_handle,
IOCTL_PRIVCMD_HYPERCALL,
(unsigned long)hypercall);
}
static inline int do_policy_op(int xc_handle, policy_op_t *op)
{
int ret = -1;
privcmd_hypercall_t hypercall;
op->interface_version = POLICY_INTERFACE_VERSION;
hypercall.op = __HYPERVISOR_policy_op;
hypercall.arg[0] = (unsigned long)op;
if ( mlock(op, sizeof(*op)) != 0 )
{
PERROR("Could not lock memory for Xen policy hypercall");
goto out1;
}
if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
{
if ( errno == EACCES )
fprintf(stderr, "POLICY operation failed -- need to"
" rebuild the user-space tool set?\n");
goto out2;
}
out2: (void)munlock(op, sizeof(*op));
out1: return ret;
}
/*************************** DUMPS *******************************/
void acm_dump_chinesewall_buffer(void *buf, int buflen) {
struct acm_chwall_policy_buffer *cwbuf = (struct acm_chwall_policy_buffer *)buf;
domaintype_t *ssids, *conflicts, *running_types, *conflict_aggregate;
int i,j;
if (htons(cwbuf->policy_code) != ACM_CHINESE_WALL_POLICY) {
printf("CHINESE WALL POLICY CODE not found ERROR!!\n");
return;
}
printf("\n\nChinese Wall policy:\n");
printf("====================\n");
printf("Max Types = %x.\n", ntohs(cwbuf->chwall_max_types));
printf("Max Ssidrefs = %x.\n", ntohs(cwbuf->chwall_max_ssidrefs));
printf("Max ConfSets = %x.\n", ntohs(cwbuf->chwall_max_conflictsets));
printf("Ssidrefs Off = %x.\n", ntohs(cwbuf->chwall_ssid_offset));
printf("Conflicts Off = %x.\n", ntohs(cwbuf->chwall_conflict_sets_offset));
printf("Runing T. Off = %x.\n", ntohs(cwbuf->chwall_running_types_offset));
printf("C. Agg. Off = %x.\n", ntohs(cwbuf->chwall_conflict_aggregate_offset));
printf("\nSSID To CHWALL-Type matrix:\n");
ssids = (domaintype_t *)(buf + ntohs(cwbuf->chwall_ssid_offset));
for(i=0; i< ntohs(cwbuf->chwall_max_ssidrefs); i++) {
printf("\n ssidref%2x: ", i);
for(j=0; j< ntohs(cwbuf->chwall_max_types); j++)
printf("%02x ", ntohs(ssids[i*ntohs(cwbuf->chwall_max_types) + j]));
}
printf("\n\nConfict Sets:\n");
conflicts = (domaintype_t *)(buf + ntohs(cwbuf->chwall_conflict_sets_offset));
for(i=0; i< ntohs(cwbuf->chwall_max_conflictsets); i++) {
printf("\n c-set%2x: ", i);
for(j=0; j< ntohs(cwbuf->chwall_max_types); j++)
printf("%02x ", ntohs(conflicts[i*ntohs(cwbuf->chwall_max_types) +j]));
}
printf("\n");
printf("\nRunning\nTypes: ");
if (ntohs(cwbuf->chwall_running_types_offset)) {
running_types = (domaintype_t *)(buf + ntohs(cwbuf->chwall_running_types_offset));
for(i=0; i< ntohs(cwbuf->chwall_max_types); i++) {
printf("%02x ", ntohs(running_types[i]));
}
printf("\n");
} else {
printf("Not Reported!\n");
}
printf("\nConflict\nAggregate Set: ");
if (ntohs(cwbuf->chwall_conflict_aggregate_offset)) {
conflict_aggregate = (domaintype_t *)(buf + ntohs(cwbuf->chwall_conflict_aggregate_offset));
for(i=0; i< ntohs(cwbuf->chwall_max_types); i++) {
printf("%02x ", ntohs(conflict_aggregate[i]));
}
printf("\n\n");
} else {
printf("Not Reported!\n");
}
}
void acm_dump_ste_buffer(void *buf, int buflen) {
struct acm_ste_policy_buffer *stebuf = (struct acm_ste_policy_buffer *)buf;
domaintype_t *ssids;
int i,j;
if (ntohs(stebuf->policy_code) != ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
printf("SIMPLE TYPE ENFORCEMENT POLICY CODE not found ERROR!!\n");
return;
}
printf("\nSimple Type Enforcement policy:\n");
printf("===============================\n");
printf("Max Types = %x.\n", ntohs(stebuf->ste_max_types));
printf("Max Ssidrefs = %x.\n", ntohs(stebuf->ste_max_ssidrefs));
printf("Ssidrefs Off = %x.\n", ntohs(stebuf->ste_ssid_offset));
printf("\nSSID To STE-Type matrix:\n");
ssids = (domaintype_t *)(buf + ntohs(stebuf->ste_ssid_offset));
for(i=0; i< ntohs(stebuf->ste_max_ssidrefs); i++) {
printf("\n ssidref%2x: ", i);
for(j=0; j< ntohs(stebuf->ste_max_types); j++)
printf("%02x ", ntohs(ssids[i*ntohs(stebuf->ste_max_types) +j]));
}
printf("\n\n");
}
void acm_dump_policy_buffer(void *buf, int buflen) {
struct acm_policy_buffer *pol = (struct acm_policy_buffer *)buf;
printf("\nPolicy dump:\n");
printf("============\n");
printf("Magic = %x.\n", ntohl(pol->magic));
printf("PolVer = %x.\n", ntohl(pol->policyversion));
printf("Len = %x.\n", ntohl(pol->len));
printf("Primary = %s (c=%x, off=%x).\n",
ACM_POLICY_NAME(ntohs(pol->primary_policy_code)),
ntohs(pol->primary_policy_code), ntohs(pol->primary_buffer_offset));
printf("Secondary = %s (c=%x, off=%x).\n",
ACM_POLICY_NAME(ntohs(pol->secondary_policy_code)),
ntohs(pol->secondary_policy_code), ntohs(pol->secondary_buffer_offset));
switch (ntohs(pol->primary_policy_code)) {
case ACM_CHINESE_WALL_POLICY:
acm_dump_chinesewall_buffer(buf+ntohs(pol->primary_buffer_offset),
ntohl(pol->len) - ntohs(pol->primary_buffer_offset));
break;
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
acm_dump_ste_buffer(buf+ntohs(pol->primary_buffer_offset),
ntohl(pol->len) - ntohs(pol->primary_buffer_offset));
break;
case ACM_NULL_POLICY:
printf("Primary policy is NULL Policy (n/a).\n");
break;
default:
printf("UNKNOWN POLICY!\n");
}
switch (ntohs(pol->secondary_policy_code)) {
case ACM_CHINESE_WALL_POLICY:
acm_dump_chinesewall_buffer(buf+ntohs(pol->secondary_buffer_offset),
ntohl(pol->len) - ntohs(pol->secondary_buffer_offset));
break;
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
acm_dump_ste_buffer(buf+ntohs(pol->secondary_buffer_offset),
ntohl(pol->len) - ntohs(pol->secondary_buffer_offset));
break;
case ACM_NULL_POLICY:
printf("Secondary policy is NULL Policy (n/a).\n");
break;
default:
printf("UNKNOWN POLICY!\n");
}
printf("\nPolicy dump End.\n\n");
}
/*************************** set policy ****************************/
int acm_domain_set_chwallpolicy(void *bufstart, int buflen) {
#define CWALL_MAX_SSIDREFS 5
#define CWALL_MAX_TYPES 10
#define CWALL_MAX_CONFLICTSETS 2
struct acm_chwall_policy_buffer *chwall_bin_pol = (struct acm_chwall_policy_buffer *)bufstart;
domaintype_t *ssidrefs, *conflicts;
int ret = 0;
int i,j;
chwall_bin_pol->chwall_max_types = htons(CWALL_MAX_TYPES);
chwall_bin_pol->chwall_max_ssidrefs = htons(CWALL_MAX_SSIDREFS);
chwall_bin_pol->policy_code = htons(ACM_CHINESE_WALL_POLICY);
chwall_bin_pol->chwall_ssid_offset = htons(sizeof(struct acm_chwall_policy_buffer));
chwall_bin_pol->chwall_max_conflictsets = htons(CWALL_MAX_CONFLICTSETS);
chwall_bin_pol->chwall_conflict_sets_offset =
htons(
ntohs(chwall_bin_pol->chwall_ssid_offset) +
sizeof(domaintype_t)*CWALL_MAX_SSIDREFS*CWALL_MAX_TYPES);
chwall_bin_pol->chwall_running_types_offset = 0; /* not set */
chwall_bin_pol->chwall_conflict_aggregate_offset = 0; /* not set */
ret += sizeof(struct acm_chwall_policy_buffer);
/* now push example ssids into the buffer (max_ssidrefs x max_types entries) */
/* check buffer size */
if ((buflen - ret) < (CWALL_MAX_TYPES*CWALL_MAX_SSIDREFS*sizeof(domaintype_t)))
return -1; /* not enough space */
ssidrefs = (domaintype_t *)(bufstart+ntohs(chwall_bin_pol->chwall_ssid_offset));
for(i=0; i< CWALL_MAX_SSIDREFS; i++) {
for (j=0; j< CWALL_MAX_TYPES; j++)
ssidrefs[i*CWALL_MAX_TYPES + j] = htons(0);
/* here, set type i for ssidref i; generally, a ssidref can have multiple chwall types */
if (i < CWALL_MAX_SSIDREFS)
ssidrefs[i*CWALL_MAX_TYPES + i] = htons(1);
}
ret += CWALL_MAX_TYPES*CWALL_MAX_SSIDREFS*sizeof(domaintype_t);
if ((buflen - ret) < (CWALL_MAX_CONFLICTSETS*CWALL_MAX_TYPES*sizeof(domaintype_t)))
return -1; /* not enough space */
/* now the chinese wall policy conflict sets*/
conflicts = (domaintype_t *)(bufstart +
ntohs(chwall_bin_pol->chwall_conflict_sets_offset));
memset((void *)conflicts, 0, CWALL_MAX_CONFLICTSETS*CWALL_MAX_TYPES*sizeof(domaintype_t));
/* just 1 conflict set [0]={2,3}, [1]={0,5,6} */
if (CWALL_MAX_TYPES > 3) {
conflicts[2] = htons(1); conflicts[3] = htons(1); /* {2,3} */
conflicts[CWALL_MAX_TYPES] = htons(1); conflicts[CWALL_MAX_TYPES+5] = htons(1);
conflicts[CWALL_MAX_TYPES+6] = htons(1);/* {0,5,6} */
}
ret += sizeof(domaintype_t)*CWALL_MAX_CONFLICTSETS*CWALL_MAX_TYPES;
return ret;
}
int acm_domain_set_stepolicy(void *bufstart, int buflen) {
#define STE_MAX_SSIDREFS 5
#define STE_MAX_TYPES 5
struct acm_ste_policy_buffer *ste_bin_pol = (struct acm_ste_policy_buffer *)bufstart;
domaintype_t *ssidrefs;
int i,j, ret = 0;
ste_bin_pol->ste_max_types = htons(STE_MAX_TYPES);
ste_bin_pol->ste_max_ssidrefs = htons(STE_MAX_SSIDREFS);
ste_bin_pol->policy_code = htons(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
ste_bin_pol->ste_ssid_offset = htons(sizeof(struct acm_ste_policy_buffer));
ret += sizeof(struct acm_ste_policy_buffer);
/* check buffer size */
if ((buflen - ret) < (STE_MAX_TYPES*STE_MAX_SSIDREFS*sizeof(domaintype_t)))
return -1; /* not enough space */
ssidrefs = (domaintype_t *)(bufstart+ntohs(ste_bin_pol->ste_ssid_offset));
for(i=0; i< STE_MAX_SSIDREFS; i++) {
for (j=0; j< STE_MAX_TYPES; j++)
ssidrefs[i*STE_MAX_TYPES + j] = htons(0);
/* set type i in ssidref 0 and ssidref i */
ssidrefs[i] = htons(1); /* ssidref 0 has all types set */
if (i < STE_MAX_SSIDREFS)
ssidrefs[i*STE_MAX_TYPES + i] = htons(1);
}
ret += STE_MAX_TYPES*STE_MAX_SSIDREFS*sizeof(domaintype_t);
return ret;
}
#define MAX_PUSH_BUFFER 16384
u8 push_buffer[MAX_PUSH_BUFFER];
int acm_domain_setpolicy(int xc_handle)
{
int ret;
struct acm_policy_buffer *bin_pol;
policy_op_t op;
/* future: read policy from file and set it */
bin_pol = (struct acm_policy_buffer *)push_buffer;
bin_pol->magic = htonl(ACM_MAGIC);
bin_pol->policyversion = htonl(POLICY_INTERFACE_VERSION);
bin_pol->primary_policy_code = htons(ACM_CHINESE_WALL_POLICY);
bin_pol->secondary_policy_code = htons(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
bin_pol->len = htonl(sizeof(struct acm_policy_buffer));
bin_pol->primary_buffer_offset = htons(ntohl(bin_pol->len));
ret = acm_domain_set_chwallpolicy(push_buffer + ntohs(bin_pol->primary_buffer_offset),
MAX_PUSH_BUFFER - ntohs(bin_pol->primary_buffer_offset));
if (ret < 0) {
printf("ERROR creating chwallpolicy buffer.\n");
return -1;
}
bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
bin_pol->secondary_buffer_offset = htons(ntohl(bin_pol->len));
ret = acm_domain_set_stepolicy(push_buffer + ntohs(bin_pol->secondary_buffer_offset),
MAX_PUSH_BUFFER - ntohs(bin_pol->secondary_buffer_offset));
if (ret < 0) {
printf("ERROR creating chwallpolicy buffer.\n");
return -1;
}
bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
/* dump it and then push it down into xen/acm */
acm_dump_policy_buffer(push_buffer, ntohl(bin_pol->len));
op.cmd = POLICY_SETPOLICY;
op.u.setpolicy.pushcache = (void *)push_buffer;
op.u.setpolicy.pushcache_size = ntohl(bin_pol->len);
op.u.setpolicy.policy_type = ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY;
ret = do_policy_op(xc_handle, &op);
if (ret)
printf("ERROR setting policy. Use 'xm dmesg' to see details.\n");
else
printf("Successfully changed policy.\n");
return ret;
}
/******************************* get policy ******************************/
#define PULL_CACHE_SIZE 8192
u8 pull_buffer[PULL_CACHE_SIZE];
int acm_domain_getpolicy(int xc_handle)
{
policy_op_t op;
int ret;
memset(pull_buffer, 0x00, sizeof(pull_buffer));
op.cmd = POLICY_GETPOLICY;
op.u.getpolicy.pullcache = (void *)pull_buffer;
op.u.getpolicy.pullcache_size = sizeof(pull_buffer);
ret = do_policy_op(xc_handle, &op);
/* dump policy */
acm_dump_policy_buffer(pull_buffer, sizeof(pull_buffer));
return ret;
}
/************************ load binary policy ******************************/
int acm_domain_loadpolicy(int xc_handle,
const char *filename)
{
struct stat mystat;
int ret, fd;
off_t len;
u8 *buffer;
if ((ret = stat(filename, &mystat))) {
printf("File %s not found.\n",filename);
goto out;
}
len = mystat.st_size;
if ((buffer = malloc(len)) == NULL) {
ret = -ENOMEM;
goto out;
}
if ((fd = open(filename, O_RDONLY)) <= 0) {
ret = -ENOENT;
printf("File %s not found.\n",filename);
goto free_out;
}
if (len == read(fd, buffer, len)) {
policy_op_t op;
/* dump it and then push it down into xen/acm */
acm_dump_policy_buffer(buffer, len);
op.cmd = POLICY_SETPOLICY;
op.u.setpolicy.pushcache = (void *)buffer;
op.u.setpolicy.pushcache_size = len;
op.u.setpolicy.policy_type = ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY;
ret = do_policy_op(xc_handle, &op);
if (ret)
printf("ERROR setting policy. Use 'xm dmesg' to see details.\n");
else
printf("Successfully changed policy.\n");
} else {
ret = -1;
}
close(fd);
free_out:
free(buffer);
out:
return ret;
}
/************************ dump hook statistics ******************************/
void
dump_ste_stats(struct acm_ste_stats_buffer *ste_stats)
{
printf("STE-Policy Security Hook Statistics:\n");
printf("ste: event_channel eval_count = %d\n", ntohl(ste_stats->ec_eval_count));
printf("ste: event_channel denied_count = %d\n", ntohl(ste_stats->ec_denied_count));
printf("ste: event_channel cache_hit_count = %d\n", ntohl(ste_stats->ec_cachehit_count));
printf("ste:\n");
printf("ste: grant_table eval_count = %d\n", ntohl(ste_stats->gt_eval_count));
printf("ste: grant_table denied_count = %d\n", ntohl(ste_stats->gt_denied_count));
printf("ste: grant_table cache_hit_count = %d\n", ntohl(ste_stats->gt_cachehit_count));
}
#define PULL_STATS_SIZE 8192
int acm_domain_dumpstats(int xc_handle)
{
u8 stats_buffer[PULL_STATS_SIZE];
policy_op_t op;
int ret;
struct acm_stats_buffer *stats;
memset(stats_buffer, 0x00, sizeof(stats_buffer));
op.cmd = POLICY_DUMPSTATS;
op.u.dumpstats.pullcache = (void *)stats_buffer;
op.u.dumpstats.pullcache_size = sizeof(stats_buffer);
ret = do_policy_op(xc_handle, &op);
if (ret < 0) {
printf("ERROR dumping policy stats. Use 'xm dmesg' to see details.\n");
return ret;
}
stats = (struct acm_stats_buffer *)stats_buffer;
printf("\nPolicy dump:\n");
printf("============\n");
printf("Magic = %x.\n", ntohl(stats->magic));
printf("PolVer = %x.\n", ntohl(stats->policyversion));
printf("Len = %x.\n", ntohl(stats->len));
switch(ntohs(stats->primary_policy_code)) {
case ACM_NULL_POLICY:
printf("NULL Policy: No statistics apply.\n");
break;
case ACM_CHINESE_WALL_POLICY:
printf("Chinese Wall Policy: No statistics apply.\n");
break;
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
dump_ste_stats((struct acm_ste_stats_buffer *)(stats_buffer + ntohs(stats->primary_stats_offset)));
break;
default:
printf("UNKNOWN PRIMARY POLICY ERROR!\n");
}
switch(ntohs(stats->secondary_policy_code)) {
case ACM_NULL_POLICY:
printf("NULL Policy: No statistics apply.\n");
break;
case ACM_CHINESE_WALL_POLICY:
printf("Chinese Wall Policy: No statistics apply.\n");
break;
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
dump_ste_stats((struct acm_ste_stats_buffer *)(stats_buffer + ntohs(stats->secondary_stats_offset)));
break;
default:
printf("UNKNOWN SECONDARY POLICY ERROR!\n");
}
return ret;
}
/***************************** main **************************************/
void
usage(char *progname){
printf("Use: %s \n"
"\t setpolicy\n"
"\t getpolicy\n"
"\t dumpstats\n"
"\t loadpolicy <binary policy file>\n", progname);
exit(-1);
}
int
main(int argc, char **argv) {
int policycmd_fd;
if (argc < 2)
usage(argv[0]);
if ((policycmd_fd = open("/proc/xen/privcmd", O_RDONLY)) <= 0) {
printf("ERROR: Could not open xen policycmd device!\n");
exit(-1);
}
if (!strcmp(argv[1], "setpolicy")) {
if (argc != 2)
usage(argv[0]);
acm_domain_setpolicy(policycmd_fd);
} else if (!strcmp(argv[1], "getpolicy")) {
if (argc != 2)
usage(argv[0]);
acm_domain_getpolicy(policycmd_fd);
} else if (!strcmp(argv[1], "loadpolicy")) {
if (argc != 3)
usage(argv[0]);
acm_domain_loadpolicy(policycmd_fd, argv[2]);
} else if (!strcmp(argv[1], "dumpstats")) {
if (argc != 2)
usage(argv[0]);
acm_domain_dumpstats(policycmd_fd);
} else
usage(argv[0]);
close(policycmd_fd);
return 0;
}
+6 -4
View File
@@ -78,13 +78,14 @@ static PyObject *pyxc_domain_create(PyObject *self,
u32 dom = 0;
int ret;
u32 ssidref = 0xFFFFFFFF;
static char *kwd_list[] = { "dom", NULL };
static char *kwd_list[] = { "dom", "ssidref", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &dom))
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list, &dom, &ssidref))
return NULL;
if ( (ret = xc_domain_create(xc->xc_handle, &dom)) < 0 )
if ( (ret = xc_domain_create(xc->xc_handle, ssidref, &dom)) < 0 )
return PyErr_SetFromErrno(xc_error);
return PyInt_FromLong(dom);
@@ -230,7 +231,7 @@ static PyObject *pyxc_domain_getinfo(PyObject *self,
}
info_dict = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
",s:l,s:L,s:l,s:i}",
",s:l,s:L,s:l,s:i,s:i}",
"dom", info[i].domid,
"vcpus", info[i].vcpus,
"dying", info[i].dying,
@@ -242,6 +243,7 @@ static PyObject *pyxc_domain_getinfo(PyObject *self,
"mem_kb", info[i].nr_pages*4,
"cpu_time", info[i].cpu_time,
"maxmem_kb", info[i].max_memkb,
"ssidref", info[i].ssidref,
"shutdown_reason", info[i].shutdown_reason);
PyDict_SetItemString( info_dict, "vcpu_to_cpu", vcpu_list );
PyDict_SetItemString( info_dict, "cpumap", cpumap_list );
+47 -29
View File
@@ -1,7 +1,7 @@
/*
Python interface to the Xen Store Daemon.
Copyright (C) 2005 Mike Wray Hewlett-Packard
*/
* Python interface to the Xen Store Daemon.
* Copyright (C) 2005 Mike Wray Hewlett-Packard
*/
#include <Python.h>
@@ -196,6 +196,7 @@ static PyObject *xspy_mkdir(PyObject *self, PyObject *args, PyObject *kwds)
#define xspy_rm_doc "\n" \
"Remove a path.\n" \
" path [string] : path to remove\n" \
"\n" \
"Returns: [int] 0 on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
@@ -339,13 +340,14 @@ static PyObject *xspy_set_permissions(PyObject *self, PyObject *args,
return val;
}
#define xspy_watch_doc "\n" \
"Watch a path, get notifications when it changes.\n" \
" path [string] : xenstore path.\n" \
" token [string] : returned in watch notification\n" \
"\n" \
"Returns: [int] 0 on success.\n" \
"Raises RuntimeError on error.\n" \
#define xspy_watch_doc "\n" \
"Watch a path, get notifications when it changes.\n" \
" path [string] : xenstore path.\n" \
" priority [int] : watch priority (default 0).\n" \
" token [string] : returned in watch notification.\n" \
"\n" \
"Returns: [int] 0 on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_watch(PyObject *self, PyObject *args, PyObject *kwds)
@@ -371,12 +373,14 @@ static PyObject *xspy_watch(PyObject *self, PyObject *args, PyObject *kwds)
return val;
}
#define xspy_read_watch_doc "\n" \
"Read a watch notification.\n" \
" path [string]: xenstore path.\n" \
"\n" \
"Returns: [tuple] (path, token).\n" \
"Raises RuntimeError on error.\n" \
#define xspy_read_watch_doc "\n" \
"Read a watch notification.\n" \
"The notification must be acknowledged by passing\n" \
"the token to acknowledge_watch().\n" \
" path [string]: xenstore path.\n" \
"\n" \
"Returns: [tuple] (path, token).\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_read_watch(PyObject *self, PyObject *args,
@@ -408,7 +412,7 @@ static PyObject *xspy_read_watch(PyObject *self, PyObject *args,
#define xspy_acknowledge_watch_doc "\n" \
"Acknowledge a watch notification that has been read.\n" \
" token [string] : returned in watch notification\n" \
" token [string] : from the watch notification\n" \
"\n" \
"Returns: [int] 0 on success.\n" \
"Raises RuntimeError on error.\n" \
@@ -499,7 +503,7 @@ static PyObject *xspy_transaction_start(PyObject *self, PyObject *args,
#define xspy_transaction_end_doc "\n" \
"End the current transaction.\n" \
"Attempts to commit the transaction unless abort is true.\n" \
" abort [int]: Abort flag..\n" \
" abort [int]: abort flag (default 0).\n" \
"\n" \
"Returns: [int] 0 on success.\n" \
"Raises RuntimeError on error.\n" \
@@ -556,10 +560,7 @@ static PyObject *xspy_introduce_domain(PyObject *self, PyObject *args,
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
&dom, &page, &port, &path))
goto exit;
printf("%s> dom=%u page=0x%08lx port=%u path=%s\n", __FUNCTION__, dom,
page, port, path);
xsval = xs_introduce_domain(xh, dom, page, port, path);
printf("%s> xsval=%d\n", __FUNCTION__, xsval);
val = pyvalue_int(xsval);
exit:
return val;
@@ -590,9 +591,7 @@ static PyObject *xspy_release_domain(PyObject *self, PyObject *args,
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
&dom))
goto exit;
printf("%s> dom=%u\n", __FUNCTION__, dom);
xsval = xs_release_domain(xh, dom);
printf("%s> xsval=%d\n", __FUNCTION__, xsval);
val = pyvalue_int(xsval);
exit:
return val;
@@ -651,6 +650,28 @@ static PyObject *xspy_shutdown(PyObject *self, PyObject *args, PyObject *kwds)
return val;
}
#define xspy_fileno_doc "\n" \
"Get the file descriptor of the xenstore socket.\n" \
"Allows an xs object to be passed to select().\n" \
"\n" \
"Returns: [int] file descriptor.\n" \
"\n"
static PyObject *xspy_fileno(PyObject *self, PyObject *args, PyObject *kwds)
{
static char *kwd_spec[] = { NULL };
static char *arg_spec = "";
struct xs_handle *xh = xshandle(self);
PyObject *val = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
goto exit;
val = PyInt_FromLong((xh ? xs_fileno(xh) : -1));
exit:
return val;
}
#define XSPY_METH(_name) { \
.ml_name = #_name, \
.ml_meth = (PyCFunction) xspy_ ## _name, \
@@ -675,17 +696,14 @@ static PyMethodDef xshandle_methods[] = {
XSPY_METH(release_domain),
XSPY_METH(close),
XSPY_METH(shutdown),
XSPY_METH(fileno),
{ /* Terminator. */ },
};
static PyObject *xshandle_getattr(PyObject *self, char *name)
{
PyObject *val = NULL;
if (strcmp(name, "fileno") == 0) {
struct xs_handle *xh = xshandle(self);
val = PyInt_FromLong((xh ? xs_fileno(xh) : -1));
} else
val = Py_FindMethod(xshandle_methods, self, name);
val = Py_FindMethod(xshandle_methods, self, name);
return val;
}
@@ -754,7 +772,7 @@ static PyMethodDef xs_methods[] = {
"Raises RuntimeError on error.\n"
"\n"
},
{ NULL, NULL, 0, NULL }
{ /* Terminator. */ }
};
PyMODINIT_FUNC initxs (void)
+14 -6
View File
@@ -202,7 +202,9 @@ class XendDomainInfo:
"""
db = parentdb.addChild(uuid)
vm = cls(db)
id = xc.domain_create()
ssidref = int(sxp.child_value(config, 'ssidref'))
log.debug('restoring with ssidref='+str(ssidref))
id = xc.domain_create(ssidref = ssidref)
vm.setdom(id)
try:
vm.restore = True
@@ -241,6 +243,7 @@ class XendDomainInfo:
self.start_time = None
self.name = None
self.memory = None
self.ssidref = None
self.image = None
self.channel = None
@@ -316,6 +319,7 @@ class XendDomainInfo:
"""
self.info = info
self.memory = self.info['mem_kb'] / 1024
self.ssidref = self.info['ssidref']
def state_set(self, state):
self.state_updated.acquire()
@@ -336,6 +340,7 @@ class XendDomainInfo:
s += " id=" + str(self.id)
s += " name=" + self.name
s += " memory=" + str(self.memory)
s += " ssidref=" + str(self.ssidref)
console = self.getConsole()
if console:
s += " console=" + str(console.console_port)
@@ -398,7 +403,8 @@ class XendDomainInfo:
sxpr = ['domain',
['id', self.id],
['name', self.name],
['memory', self.memory] ]
['memory', self.memory],
['ssidref', self.ssidref] ]
if self.uuid:
sxpr.append(['uuid', self.uuid])
if self.info:
@@ -511,7 +517,7 @@ class XendDomainInfo:
self.configure_restart()
self.construct_image()
self.configure()
self.exportToDB()
self.exportToDB(save=True)
except Exception, ex:
# Catch errors, cleanup and re-raise.
print 'Domain construction error:', ex
@@ -523,7 +529,7 @@ class XendDomainInfo:
def register_domain(self):
xd = get_component('xen.xend.XendDomain')
xd._add_domain(self)
self.exportToDB()
self.exportToDB(save=True)
def configure_cpus(self, config):
try:
@@ -533,6 +539,7 @@ class XendDomainInfo:
self.memory = int(sxp.child_value(config, 'memory'))
if self.memory is None:
raise VmError('missing memory size')
self.ssidref = int(sxp.child_value(config, 'ssidref'))
cpu = sxp.child_value(config, 'cpu')
if self.recreate and self.id and cpu is not None and int(cpu) >= 0:
xc.domain_pincpu(self.id, 0, 1<<int(cpu))
@@ -644,7 +651,7 @@ class XendDomainInfo:
def show(self):
"""Print virtual machine info.
"""
print "[VM dom=%d name=%s memory=%d" % (self.id, self.name, self.memory)
print "[VM dom=%d name=%s memory=%d ssidref=%d" % (self.id, self.name, self.memory, self.ssidref)
print "image:"
sxp.show(self.image)
print "]"
@@ -660,7 +667,7 @@ class XendDomainInfo:
cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
except:
raise VmError('invalid cpu')
id = self.image.initDomain(self.id, self.memory, cpu, self.cpu_weight)
id = self.image.initDomain(self.id, self.memory, self.ssidref, cpu, self.cpu_weight)
log.debug('init_domain> Created domain=%d name=%s memory=%d',
id, self.name, self.memory)
self.setdom(id)
@@ -1011,6 +1018,7 @@ addImageHandlerClass(VmxImageHandler)
# Ignore the fields we already handle.
add_config_handler('name', vm_field_ignore)
add_config_handler('memory', vm_field_ignore)
add_config_handler('ssidref', vm_field_ignore)
add_config_handler('cpu', vm_field_ignore)
add_config_handler('cpu_weight', vm_field_ignore)
add_config_handler('console', vm_field_ignore)
+3 -3
View File
@@ -111,7 +111,7 @@ class ImageHandler:
except OSError, ex:
log.warning("error removing bootloader file '%s': %s", f, ex)
def initDomain(self, dom, memory, cpu, cpu_weight):
def initDomain(self, dom, memory, ssidref, cpu, cpu_weight):
"""Initial domain create.
@return domain id
@@ -119,14 +119,14 @@ class ImageHandler:
mem_kb = self.getDomainMemory(memory)
if not self.vm.restore:
dom = xc.domain_create(dom = dom or 0)
dom = xc.domain_create(dom = dom or 0, ssidref = ssidref)
# if bootloader, unlink here. But should go after buildDomain() ?
if self.vm.bootloader:
self.unlink(self.kernel)
self.unlink(self.ramdisk)
if dom <= 0:
raise VmError('Creating domain failed: name=%s' % self.vm.name)
log.debug("initDomain: cpu=%d mem_kb=%d dom=%d", cpu, mem_kb, dom)
log.debug("initDomain: cpu=%d mem_kb=%d ssidref=%d dom=%d", cpu, mem_kb, ssidref, dom)
# xc.domain_setuuid(dom, uuid)
xc.domain_setcpuweight(dom, cpu_weight)
xc.domain_setmaxmem(dom, mem_kb)
@@ -142,6 +142,7 @@ class SrvDomainDir(SrvDir):
% (url, d.name, d.name))
req.write('id=%s' % d.id)
req.write('memory=%d'% d.memory)
req.write('ssidref=%d'% d.ssidref)
req.write('</li>')
req.write('</ul>')
+4 -1
View File
@@ -50,6 +50,9 @@ class BlkifBackend:
def getId(self):
return self.id
def getEvtchn(self):
return self.evtchn
def closeEvtchn(self):
if self.evtchn:
channel.eventChannelClose(self.evtchn)
@@ -198,7 +201,7 @@ class BlkDev(Dev):
backend = self.getBackend()
if backend and backend.evtchn:
db = self.db.addChild("evtchn")
backend.evtchn.exportToDB(db, save=save)
backend.evtchn.saveToDB(db, save=save)
def init(self, recreate=False, reboot=False):
self.frontendDomain = self.getDomain()
+1 -1
View File
@@ -95,7 +95,7 @@ class NetDev(Dev):
Dev.exportToDB(self, save=save)
if self.evtchn:
db = self.db.addChild("evtchn")
self.evtchn.exportToDB(db, save=save)
self.evtchn.saveToDB(db, save=save)
def init(self, recreate=False, reboot=False):
self.destroyed = False
+1 -1
View File
@@ -64,7 +64,7 @@ class Watcher:
def fileno(self):
if self.xs:
return self.xs.fileno
return self.xs.fileno()
else:
return -1
+6 -1
View File
@@ -120,6 +120,10 @@ gopts.var('memory', val='MEMORY',
fn=set_int, default=128,
use="Domain memory in MB.")
gopts.var('ssidref', val='SSIDREF',
fn=set_u32, default=0xffffffff,
use="Security Identifier.")
gopts.var('maxmem', val='MEMORY',
fn=set_int, default=None,
use="Maximum domain memory in MB.")
@@ -405,7 +409,8 @@ def make_config(opts, vals):
config = ['vm',
['name', vals.name ],
['memory', vals.memory ]]
['memory', vals.memory ],
['ssidref', vals.ssidref ]]
if vals.maxmem:
config.append(['maxmem', vals.maxmem])
if vals.cpu is not None:
+7 -3
View File
@@ -383,7 +383,7 @@ class ProgList(Prog):
self.brief_list(doms)
def brief_list(self, doms):
print 'Name Id Mem(MB) CPU VCPU(s) State Time(s) Console'
print 'Name Id Mem(MB) CPU VCPU(s) State Time(s) Console SSID-REF'
for dom in doms:
info = server.xend_domain(dom)
d = {}
@@ -399,8 +399,12 @@ class ProgList(Prog):
d['port'] = sxp.child_value(console, 'console_port')
else:
d['port'] = ''
print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3d %(vcpus)5d %(state)5s %(cpu_time)7.1f %(port)4s"
% d)
if ((int(sxp.child_value(info, 'ssidref', '-1'))) != -1):
d['ssidref1'] = int(sxp.child_value(info, 'ssidref', '-1')) & 0xffff
d['ssidref2'] = (int(sxp.child_value(info, 'ssidref', '-1')) >> 16) & 0xffff
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)
else:
print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3d %(vcpus)5d %(state)5s %(cpu_time)7.1f %(port)4s default" % d)
def show_vcpus(self, doms):
print 'Name Id VCPU CPU CPUMAP'
+7
View File
@@ -451,6 +451,13 @@ def set_bool(opt, k, v):
else:
opt.opts.err('Invalid value:' +v)
def set_u32(opt, k, v):
"""Set an option to an u32 value."""
try:
v = u32(v)
except:
opt.opts.err('Invalid value: ' + str(v))
opt.set(v)
def set_value(opt, k, v):
"""Set an option to a value."""
+3 -1
View File
@@ -46,6 +46,7 @@ clean: delete-unfresh-files
$(MAKE) -C tools clean
$(MAKE) -C common clean
$(MAKE) -C drivers clean
$(MAKE) -C acm clean
$(MAKE) -C arch/$(TARGET_ARCH) clean
rm -f include/asm *.o $(TARGET)* *~ core
rm -f include/asm-*/asm-offsets.h
@@ -58,6 +59,7 @@ $(TARGET): delete-unfresh-files
$(MAKE) include/asm-$(TARGET_ARCH)/asm-offsets.h
$(MAKE) -C common
$(MAKE) -C drivers
$(MAKE) -C acm
$(MAKE) -C arch/$(TARGET_ARCH)
# drivers/char/console.o may contain static banner/compile info. Blow it away.
@@ -109,7 +111,7 @@ include/asm-$(TARGET_ARCH)/asm-offsets.h: arch/$(TARGET_ARCH)/asm-offsets.s
.PHONY: default debug install dist clean delete-unfresh-files TAGS tags
SUBDIRS = arch/$(TARGET_ARCH) common drivers
SUBDIRS = acm arch/$(TARGET_ARCH) common drivers
define all_sources
( find include/asm-$(TARGET_ARCH) -name SCCS -prune -o -name '*.h' -print; \
find include -type d -name SCCS -prune -o \( -name "asm-*" -o \
+1
View File
@@ -35,6 +35,7 @@ OBJS += $(patsubst %.c,%.o,$(C_SRCS))
ALL_OBJS := $(BASEDIR)/common/common.o
ALL_OBJS += $(BASEDIR)/drivers/char/driver.o
ALL_OBJS += $(BASEDIR)/drivers/acpi/driver.o
ALL_OBJS += $(BASEDIR)/acm/acm.o
ALL_OBJS += $(BASEDIR)/arch/$(TARGET_ARCH)/arch.o
+15
View File
@@ -0,0 +1,15 @@
include $(BASEDIR)/Rules.mk
OBJS = acm_core.o
OBJS += acm_policy.o
OBJS += acm_simple_type_enforcement_hooks.o
OBJS += acm_chinesewall_hooks.o
OBJS += acm_null_hooks.o
default: acm.o
acm.o: $(OBJS)
$(LD) $(LDFLAGS) -r -o acm.o $(OBJS)
clean:
rm -f *.o *~ core
+503
View File
@@ -0,0 +1,503 @@
/****************************************************************
* acm_chinesewall_hooks.c
*
* Copyright (C) 2005 IBM Corporation
*
* Author:
* Reiner Sailer <sailer@watson.ibm.com>
*
* Contributions:
* Stefan Berger <stefanb@watson.ibm.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*
* sHype Chinese Wall Policy for Xen
* This code implements the hooks that are called
* throughout Xen operations and decides authorization
* based on domain types and Chinese Wall conflict type
* sets. The CHWALL policy decides if a new domain can be started
* based on the types of running domains and the type of the
* new domain to be started. If the new domain's type is in
* conflict with types of running domains, then this new domain
* is not allowed to be created. A domain can have multiple types,
* in which case all types of a new domain must be conflict-free
* with all types of already running domains.
*
*/
#include <xen/config.h>
#include <xen/errno.h>
#include <xen/types.h>
#include <xen/lib.h>
#include <xen/delay.h>
#include <xen/sched.h>
#include <public/acm.h>
#include <asm/atomic.h>
#include <acm/acm_core.h>
#include <acm/acm_hooks.h>
#include <acm/acm_endian.h>
/* local cache structures for chinese wall policy */
struct chwall_binary_policy chwall_bin_pol;
/*
* Initializing chinese wall policy (will be filled by policy partition
* using setpolicy command)
*/
int acm_init_chwall_policy(void)
{
/* minimal startup policy; policy write-locked already */
chwall_bin_pol.max_types = 1;
chwall_bin_pol.max_ssidrefs = 1;
chwall_bin_pol.max_conflictsets = 1;
chwall_bin_pol.ssidrefs = (domaintype_t *)xmalloc_array(domaintype_t, chwall_bin_pol.max_ssidrefs*chwall_bin_pol.max_types);
chwall_bin_pol.conflict_sets = (domaintype_t *)xmalloc_array(domaintype_t, chwall_bin_pol.max_conflictsets*chwall_bin_pol.max_types);
chwall_bin_pol.running_types = (domaintype_t *)xmalloc_array(domaintype_t, chwall_bin_pol.max_types);
chwall_bin_pol.conflict_aggregate_set = (domaintype_t *)xmalloc_array(domaintype_t, chwall_bin_pol.max_types);
if ((chwall_bin_pol.conflict_sets == NULL) || (chwall_bin_pol.running_types == NULL) ||
(chwall_bin_pol.ssidrefs == NULL) || (chwall_bin_pol.conflict_aggregate_set == NULL))
return ACM_INIT_SSID_ERROR;
/* initialize state */
memset((void *)chwall_bin_pol.ssidrefs, 0, chwall_bin_pol.max_ssidrefs*chwall_bin_pol.max_types*sizeof(domaintype_t));
memset((void *)chwall_bin_pol.conflict_sets, 0, chwall_bin_pol.max_conflictsets*chwall_bin_pol.max_types*sizeof(domaintype_t));
memset((void *)chwall_bin_pol.running_types, 0, chwall_bin_pol.max_types*sizeof(domaintype_t));
memset((void *)chwall_bin_pol.conflict_aggregate_set, 0, chwall_bin_pol.max_types*sizeof(domaintype_t));
return ACM_OK;
}
static int
chwall_init_domain_ssid(void **chwall_ssid, ssidref_t ssidref)
{
struct chwall_ssid *chwall_ssidp = xmalloc(struct chwall_ssid);
traceprintk("%s.\n", __func__);
if (chwall_ssidp == NULL)
return ACM_INIT_SSID_ERROR;
/*
* depending on wheter chwall is primary or secondary, get the respective
* part of the global ssidref (same way we'll get the partial ssid pointer)
*/
chwall_ssidp->chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
if (chwall_ssidp->chwall_ssidref >= chwall_bin_pol.max_ssidrefs) {
printkd("%s: ERROR chwall_ssidref(%x) > max(%x).\n",
__func__, chwall_ssidp->chwall_ssidref, chwall_bin_pol.max_ssidrefs-1);
xfree(chwall_ssidp);
return ACM_INIT_SSID_ERROR;
}
(*chwall_ssid) = chwall_ssidp;
printkd("%s: determined chwall_ssidref to %x.\n",
__func__, chwall_ssidp->chwall_ssidref);
return ACM_OK;
}
static void
chwall_free_domain_ssid(void *chwall_ssid)
{
traceprintk("%s.\n", __func__);
if (chwall_ssid != NULL)
xfree(chwall_ssid);
return;
}
/* dump chinese wall cache; policy read-locked already */
static int
chwall_dump_policy(u8 *buf, u16 buf_size) {
struct acm_chwall_policy_buffer *chwall_buf = (struct acm_chwall_policy_buffer *)buf;
int ret = 0;
chwall_buf->chwall_max_types = htons(chwall_bin_pol.max_types);
chwall_buf->chwall_max_ssidrefs = htons(chwall_bin_pol.max_ssidrefs);
chwall_buf->policy_code = htons(ACM_CHINESE_WALL_POLICY);
chwall_buf->chwall_ssid_offset = htons(sizeof(struct acm_chwall_policy_buffer));
chwall_buf->chwall_max_conflictsets = htons(chwall_bin_pol.max_conflictsets);
chwall_buf->chwall_conflict_sets_offset =
htons(
ntohs(chwall_buf->chwall_ssid_offset) +
sizeof(domaintype_t) * chwall_bin_pol.max_ssidrefs *
chwall_bin_pol.max_types);
chwall_buf->chwall_running_types_offset =
htons(
ntohs(chwall_buf->chwall_conflict_sets_offset) +
sizeof(domaintype_t) * chwall_bin_pol.max_conflictsets *
chwall_bin_pol.max_types);
chwall_buf->chwall_conflict_aggregate_offset =
htons(
ntohs(chwall_buf->chwall_running_types_offset) +
sizeof(domaintype_t) * chwall_bin_pol.max_types);
ret = ntohs(chwall_buf->chwall_conflict_aggregate_offset) +
sizeof(domaintype_t) * chwall_bin_pol.max_types;
/* now copy buffers over */
arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_ssid_offset)),
chwall_bin_pol.ssidrefs,
chwall_bin_pol.max_ssidrefs * chwall_bin_pol.max_types);
arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_conflict_sets_offset)),
chwall_bin_pol.conflict_sets,
chwall_bin_pol.max_conflictsets * chwall_bin_pol.max_types);
arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_running_types_offset)),
chwall_bin_pol.running_types,
chwall_bin_pol.max_types);
arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_conflict_aggregate_offset)),
chwall_bin_pol.conflict_aggregate_set,
chwall_bin_pol.max_types);
return ret;
}
/* adapt security state (running_types and conflict_aggregate_set) to all running
* domains; chwall_init_state is called when a policy is changed to bring the security
* information into a consistent state and to detect violations (return != 0).
* from a security point of view, we simulate that all running domains are re-started
*/
static int
chwall_init_state(struct acm_chwall_policy_buffer *chwall_buf, domaintype_t *ssidrefs, domaintype_t *conflict_sets,
domaintype_t *running_types, domaintype_t *conflict_aggregate_set)
{
int violation = 0, i, j;
struct chwall_ssid *chwall_ssid;
ssidref_t chwall_ssidref;
struct domain **pd;
write_lock(&domlist_lock);
/* go through all domains and adjust policy as if this domain was started now */
pd = &domain_list;
for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
chwall_ssid = GET_SSIDP(ACM_CHINESE_WALL_POLICY, (struct acm_ssid_domain *)(*pd)->ssid);
chwall_ssidref = chwall_ssid->chwall_ssidref;
traceprintk("%s: validating policy for domain %x (chwall-REF=%x).\n",
__func__, (*pd)->domain_id, chwall_ssidref);
/* a) adjust types ref-count for running domains */
for (i=0; i< chwall_buf->chwall_max_types; i++)
running_types[i] +=
ssidrefs[chwall_ssidref*chwall_buf->chwall_max_types + i];
/* b) check for conflict */
for (i=0; i< chwall_buf->chwall_max_types; i++)
if (conflict_aggregate_set[i] &&
ssidrefs[chwall_ssidref*chwall_buf->chwall_max_types + i]) {
printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i);
violation = 1;
goto out;
}
/* set violation and break out of the loop */
/* c) adapt conflict aggregate set for this domain (notice conflicts) */
for (i=0; i<chwall_buf->chwall_max_conflictsets; i++) {
int common = 0;
/* check if conflict_set_i and ssidref have common types */
for (j=0; j<chwall_buf->chwall_max_types; j++)
if (conflict_sets[i*chwall_buf->chwall_max_types + j] &&
ssidrefs[chwall_ssidref*chwall_buf->chwall_max_types + j]) {
common = 1;
break;
}
if (common == 0)
continue; /* try next conflict set */
/* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
for (j=0; j<chwall_buf->chwall_max_types; j++)
if (conflict_sets[i*chwall_buf->chwall_max_types + j] &&
!ssidrefs[chwall_ssidref*chwall_buf->chwall_max_types + j])
conflict_aggregate_set[j]++;
}
}
out:
write_unlock(&domlist_lock);
return violation;
/* returning "violation != 0" means that the currently running set of domains would
* not be possible if the new policy had been enforced before starting them; for chinese
* wall, this means that the new policy includes at least one conflict set of which
* more than one type is currently running */
}
static int
chwall_set_policy(u8 *buf, u16 buf_size)
{
/* policy write-locked already */
struct acm_chwall_policy_buffer *chwall_buf = (struct acm_chwall_policy_buffer *)buf;
void *ssids = NULL, *conflict_sets = NULL, *running_types = NULL, *conflict_aggregate_set = NULL;
/* rewrite the policy due to endianess */
chwall_buf->policy_code = ntohs(chwall_buf->policy_code);
chwall_buf->chwall_max_types = ntohs(chwall_buf->chwall_max_types);
chwall_buf->chwall_max_ssidrefs = ntohs(chwall_buf->chwall_max_ssidrefs);
chwall_buf->chwall_max_conflictsets = ntohs(chwall_buf->chwall_max_conflictsets);
chwall_buf->chwall_ssid_offset = ntohs(chwall_buf->chwall_ssid_offset);
chwall_buf->chwall_conflict_sets_offset = ntohs(chwall_buf->chwall_conflict_sets_offset);
chwall_buf->chwall_running_types_offset = ntohs(chwall_buf->chwall_running_types_offset);
chwall_buf->chwall_conflict_aggregate_offset = ntohs(chwall_buf->chwall_conflict_aggregate_offset);
/* 1. allocate new buffers */
ssids = xmalloc_array(domaintype_t, chwall_buf->chwall_max_types*chwall_buf->chwall_max_ssidrefs);
conflict_sets = xmalloc_array(domaintype_t, chwall_buf->chwall_max_conflictsets*chwall_buf->chwall_max_types);
running_types = xmalloc_array(domaintype_t,chwall_buf->chwall_max_types);
conflict_aggregate_set = xmalloc_array(domaintype_t, chwall_buf->chwall_max_types);
if ((ssids == NULL)||(conflict_sets == NULL)||(running_types == NULL)||(conflict_aggregate_set == NULL))
goto error_free;
/* 2. set new policy */
if (chwall_buf->chwall_ssid_offset + sizeof(domaintype_t) *
chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs > buf_size)
goto error_free;
arrcpy(ssids, buf + chwall_buf->chwall_ssid_offset,
sizeof(domaintype_t),
chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs);
if (chwall_buf->chwall_conflict_sets_offset + sizeof(domaintype_t) *
chwall_buf->chwall_max_types * chwall_buf->chwall_max_conflictsets > buf_size)
goto error_free;
arrcpy(conflict_sets, buf + chwall_buf->chwall_conflict_sets_offset,
sizeof(domaintype_t),
chwall_buf->chwall_max_types * chwall_buf->chwall_max_conflictsets);
/* we also use new state buffers since max_types can change */
memset(running_types, 0, sizeof(domaintype_t)*chwall_buf->chwall_max_types);
memset(conflict_aggregate_set, 0, sizeof(domaintype_t)*chwall_buf->chwall_max_types);
/* 3. now re-calculate the state for the new policy based on running domains;
* this can fail if new policy is conflicting with running domains */
if (chwall_init_state(chwall_buf, ssids, conflict_sets, running_types, conflict_aggregate_set)) {
printk("%s: New policy conflicts with running domains. Policy load aborted.\n", __func__);
goto error_free; /* new policy conflicts with running domains */
}
/* 4. free old policy buffers, replace with new ones */
chwall_bin_pol.max_types = chwall_buf->chwall_max_types;
chwall_bin_pol.max_ssidrefs = chwall_buf->chwall_max_ssidrefs;
chwall_bin_pol.max_conflictsets = chwall_buf->chwall_max_conflictsets;
if (chwall_bin_pol.ssidrefs != NULL)
xfree(chwall_bin_pol.ssidrefs);
if (chwall_bin_pol.conflict_aggregate_set != NULL)
xfree(chwall_bin_pol.conflict_aggregate_set);
if (chwall_bin_pol.running_types != NULL)
xfree(chwall_bin_pol.running_types);
if (chwall_bin_pol.conflict_sets != NULL)
xfree(chwall_bin_pol.conflict_sets);
chwall_bin_pol.ssidrefs = ssids;
chwall_bin_pol.conflict_aggregate_set = conflict_aggregate_set;
chwall_bin_pol.running_types = running_types;
chwall_bin_pol.conflict_sets = conflict_sets;
return ACM_OK;
error_free:
printk("%s: ERROR setting policy.\n", __func__);
if (ssids != NULL) xfree(ssids);
if (conflict_sets != NULL) xfree(conflict_sets);
if (running_types != NULL) xfree(running_types);
if (conflict_aggregate_set != NULL) xfree(conflict_aggregate_set);
return -EFAULT;
}
static int
chwall_dump_stats(u8 *buf, u16 len)
{
/* no stats for Chinese Wall Policy */
return 0;
}
/***************************
* Authorization functions
***************************/
/* -------- DOMAIN OPERATION HOOKS -----------*/
static int
chwall_pre_domain_create(void *subject_ssid, ssidref_t ssidref)
{
ssidref_t chwall_ssidref;
int i,j;
traceprintk("%s.\n", __func__);
read_lock(&acm_bin_pol_rwlock);
chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
if (chwall_ssidref == ACM_DEFAULT_LOCAL_SSID) {
printk("%s: ERROR CHWALL SSID is NOT SET but policy enforced.\n", __func__);
read_unlock(&acm_bin_pol_rwlock);
return ACM_ACCESS_DENIED; /* catching and indicating config error */
}
if (chwall_ssidref >= chwall_bin_pol.max_ssidrefs) {
printk("%s: ERROR chwall_ssidref > max(%x).\n",
__func__, chwall_bin_pol.max_ssidrefs-1);
read_unlock(&acm_bin_pol_rwlock);
return ACM_ACCESS_DENIED;
}
/* A: chinese wall check for conflicts */
for (i=0; i< chwall_bin_pol.max_types; i++)
if (chwall_bin_pol.conflict_aggregate_set[i] &&
chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + i]) {
printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i);
read_unlock(&acm_bin_pol_rwlock);
return ACM_ACCESS_DENIED;
}
/* B: chinese wall conflict set adjustment (so that other
* other domains simultaneously created are evaluated against this new set)*/
for (i=0; i<chwall_bin_pol.max_conflictsets; i++) {
int common = 0;
/* check if conflict_set_i and ssidref have common types */
for (j=0; j<chwall_bin_pol.max_types; j++)
if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) {
common = 1;
break;
}
if (common == 0)
continue; /* try next conflict set */
/* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
for (j=0; j<chwall_bin_pol.max_types; j++)
if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
!chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j])
chwall_bin_pol.conflict_aggregate_set[j]++;
}
read_unlock(&acm_bin_pol_rwlock);
return ACM_ACCESS_PERMITTED;
}
static void
chwall_post_domain_create(domid_t domid, ssidref_t ssidref)
{
int i,j;
ssidref_t chwall_ssidref;
traceprintk("%s.\n", __func__);
read_lock(&acm_bin_pol_rwlock);
chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
/* adjust types ref-count for running domains */
for (i=0; i< chwall_bin_pol.max_types; i++)
chwall_bin_pol.running_types[i] +=
chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + i];
if (domid) {
read_unlock(&acm_bin_pol_rwlock);
return;
}
/* Xen does not call pre-create hook for DOM0;
* to consider type conflicts of any domain with DOM0, we need
* to adjust the conflict_aggregate for DOM0 here the same way it
* is done for non-DOM0 domains in the pre-hook */
printkd("%s: adjusting security state for DOM0 (ssidref=%x, chwall_ssidref=%x).\n",
__func__, ssidref, chwall_ssidref);
/* chinese wall conflict set adjustment (so that other
* other domains simultaneously created are evaluated against this new set)*/
for (i=0; i<chwall_bin_pol.max_conflictsets; i++) {
int common = 0;
/* check if conflict_set_i and ssidref have common types */
for (j=0; j<chwall_bin_pol.max_types; j++)
if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) {
common = 1;
break;
}
if (common == 0)
continue; /* try next conflict set */
/* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
for (j=0; j<chwall_bin_pol.max_types; j++)
if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
!chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j])
chwall_bin_pol.conflict_aggregate_set[j]++;
}
read_unlock(&acm_bin_pol_rwlock);
return;
}
static void
chwall_fail_domain_create(void *subject_ssid, ssidref_t ssidref)
{
int i, j;
ssidref_t chwall_ssidref;
traceprintk("%s.\n", __func__);
read_lock(&acm_bin_pol_rwlock);
chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
/* roll-back: re-adjust conflicting types aggregate */
for (i=0; i<chwall_bin_pol.max_conflictsets; i++) {
int common = 0;
/* check if conflict_set_i and ssidref have common types */
for (j=0; j<chwall_bin_pol.max_types; j++)
if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) {
common = 1;
break;
}
if (common == 0)
continue; /* try next conflict set, this one does not include any type of chwall_ssidref */
/* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
for (j=0; j<chwall_bin_pol.max_types; j++)
if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
!chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j])
chwall_bin_pol.conflict_aggregate_set[j]--;
}
read_unlock(&acm_bin_pol_rwlock);
}
static void
chwall_post_domain_destroy(void *object_ssid, domid_t id)
{
int i,j;
struct chwall_ssid *chwall_ssidp =
GET_SSIDP(ACM_CHINESE_WALL_POLICY, (struct acm_ssid_domain *)object_ssid);
ssidref_t chwall_ssidref = chwall_ssidp->chwall_ssidref;
traceprintk("%s.\n", __func__);
read_lock(&acm_bin_pol_rwlock);
/* adjust running types set */
for (i=0; i< chwall_bin_pol.max_types; i++)
chwall_bin_pol.running_types[i] -=
chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + i];
/* roll-back: re-adjust conflicting types aggregate */
for (i=0; i<chwall_bin_pol.max_conflictsets; i++) {
int common = 0;
/* check if conflict_set_i and ssidref have common types */
for (j=0; j<chwall_bin_pol.max_types; j++)
if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) {
common = 1;
break;
}
if (common == 0)
continue; /* try next conflict set, this one does not include any type of chwall_ssidref */
/* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
for (j=0; j<chwall_bin_pol.max_types; j++)
if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
!chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j])
chwall_bin_pol.conflict_aggregate_set[j]--;
}
read_unlock(&acm_bin_pol_rwlock);
return;
}
struct acm_operations acm_chinesewall_ops = {
/* policy management services */
.init_domain_ssid = chwall_init_domain_ssid,
.free_domain_ssid = chwall_free_domain_ssid,
.dump_binary_policy = chwall_dump_policy,
.set_binary_policy = chwall_set_policy,
.dump_statistics = chwall_dump_stats,
/* domain management control hooks */
.pre_domain_create = chwall_pre_domain_create,
.post_domain_create = chwall_post_domain_create,
.fail_domain_create = chwall_fail_domain_create,
.post_domain_destroy = chwall_post_domain_destroy,
/* event channel control hooks */
.pre_eventchannel_unbound = NULL,
.fail_eventchannel_unbound = NULL,
.pre_eventchannel_interdomain = NULL,
.fail_eventchannel_interdomain = NULL,
/* grant table control hooks */
.pre_grant_map_ref = NULL,
.fail_grant_map_ref = NULL,
.pre_grant_setup = NULL,
.fail_grant_setup = NULL,
};
+205
View File
@@ -0,0 +1,205 @@
/****************************************************************
* acm_core.c
*
* Copyright (C) 2005 IBM Corporation
*
* Author:
* Reiner Sailer <sailer@watson.ibm.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*
* sHype access control module (ACM)
* This file handles initialization of the ACM
* as well as initializing/freeing security
* identifiers for domains (it calls on active
* policy hook functions).
*
*/
#include <xen/config.h>
#include <xen/errno.h>
#include <xen/types.h>
#include <xen/lib.h>
#include <xen/delay.h>
#include <xen/sched.h>
#include <acm/acm_hooks.h>
#include <acm/acm_endian.h>
/* debug:
* include/acm/acm_hooks.h defines a constant ACM_TRACE_MODE;
* define/undefine this constant to receive / suppress any
* security hook debug output of sHype
*
* include/public/acm.h defines a constant ACM_DEBUG
* define/undefine this constant to receive non-hook-related
* debug output.
*/
/* function prototypes */
void acm_init_chwall_policy(void);
void acm_init_ste_policy(void);
extern struct acm_operations acm_chinesewall_ops,
acm_simple_type_enforcement_ops, acm_null_ops;
/* global ops structs called by the hooks */
struct acm_operations *acm_primary_ops = NULL;
/* called in hook if-and-only-if primary succeeds */
struct acm_operations *acm_secondary_ops = NULL;
/* acm global binary policy (points to 'local' primary and secondary policies */
struct acm_binary_policy acm_bin_pol;
/* acm binary policy lock */
rwlock_t acm_bin_pol_rwlock = RW_LOCK_UNLOCKED;
/* until we have endian support in Xen, we discover it at runtime */
u8 little_endian = 1;
void acm_set_endian(void)
{
u32 test = 1;
if (*((u8 *)&test) == 1) {
printk("ACM module running in LITTLE ENDIAN.\n");
little_endian = 1;
} else {
printk("ACM module running in BIG ENDIAN.\n");
little_endian = 0;
}
}
/* initialize global security policy for Xen; policy write-locked already */
static void
acm_init_binary_policy(void *primary, void *secondary)
{
acm_bin_pol.primary_policy_code = 0;
acm_bin_pol.secondary_policy_code = 0;
acm_bin_pol.primary_binary_policy = primary;
acm_bin_pol.secondary_binary_policy = secondary;
}
int
acm_init(void)
{
int ret = -EINVAL;
acm_set_endian();
write_lock(&acm_bin_pol_rwlock);
if (ACM_USE_SECURITY_POLICY == ACM_CHINESE_WALL_POLICY) {
acm_init_binary_policy(NULL, NULL);
acm_init_chwall_policy();
acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
acm_primary_ops = &acm_chinesewall_ops;
acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
acm_secondary_ops = &acm_null_ops;
ret = ACM_OK;
} else if (ACM_USE_SECURITY_POLICY == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
acm_init_binary_policy(NULL, NULL);
acm_init_ste_policy();
acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
acm_primary_ops = &acm_simple_type_enforcement_ops;
acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
acm_secondary_ops = &acm_null_ops;
ret = ACM_OK;
} else if (ACM_USE_SECURITY_POLICY == ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
acm_init_binary_policy(NULL, NULL);
acm_init_chwall_policy();
acm_init_ste_policy();
acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
acm_primary_ops = &acm_chinesewall_ops;
acm_bin_pol.secondary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
acm_secondary_ops = &acm_simple_type_enforcement_ops;
ret = ACM_OK;
} else if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) {
acm_init_binary_policy(NULL, NULL);
acm_bin_pol.primary_policy_code = ACM_NULL_POLICY;
acm_primary_ops = &acm_null_ops;
acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
acm_secondary_ops = &acm_null_ops;
ret = ACM_OK;
}
write_unlock(&acm_bin_pol_rwlock);
if (ret != ACM_OK)
return -EINVAL;
printk("%s: Enforcing Primary %s, Secondary %s.\n", __func__,
ACM_POLICY_NAME(acm_bin_pol.primary_policy_code), ACM_POLICY_NAME(acm_bin_pol.secondary_policy_code));
return ACM_OK;
}
int
acm_init_domain_ssid(domid_t id, ssidref_t ssidref)
{
struct acm_ssid_domain *ssid;
struct domain *subj = find_domain_by_id(id);
int ret1, ret2;
if (subj == NULL) {
printk("%s: ACM_NULL_POINTER ERROR (id=%x).\n", __func__, id);
return ACM_NULL_POINTER_ERROR;
}
if ((ssid = xmalloc(struct acm_ssid_domain)) == NULL)
return ACM_INIT_SSID_ERROR;
ssid->datatype = DOMAIN;
ssid->subject = subj;
ssid->domainid = subj->domain_id;
ssid->primary_ssid = NULL;
ssid->secondary_ssid = NULL;
if (ACM_USE_SECURITY_POLICY != ACM_NULL_POLICY)
ssid->ssidref = ssidref;
else
ssid->ssidref = ACM_DEFAULT_SSID;
subj->ssid = ssid;
/* now fill in primary and secondary parts; we only get here through hooks */
if (acm_primary_ops->init_domain_ssid != NULL)
ret1 = acm_primary_ops->init_domain_ssid(&(ssid->primary_ssid), ssidref);
else
ret1 = ACM_OK;
if (acm_secondary_ops->init_domain_ssid != NULL)
ret2 = acm_secondary_ops->init_domain_ssid(&(ssid->secondary_ssid), ssidref);
else
ret2 = ACM_OK;
if ((ret1 != ACM_OK) || (ret2 != ACM_OK)) {
printk("%s: ERROR instantiating individual ssids for domain 0x%02x.\n",
__func__, subj->domain_id);
acm_free_domain_ssid(ssid);
put_domain(subj);
return ACM_INIT_SSID_ERROR;
}
printk("%s: assigned domain %x the ssidref=%x.\n", __func__, id, ssid->ssidref);
put_domain(subj);
return ACM_OK;
}
int
acm_free_domain_ssid(struct acm_ssid_domain *ssid)
{
domid_t id;
/* domain is already gone, just ssid is left */
if (ssid == NULL) {
printk("%s: ACM_NULL_POINTER ERROR.\n", __func__);
return ACM_NULL_POINTER_ERROR;
}
id = ssid->domainid;
ssid->subject = NULL;
if (acm_primary_ops->free_domain_ssid != NULL) /* null policy */
acm_primary_ops->free_domain_ssid(ssid->primary_ssid);
ssid->primary_ssid = NULL;
if (acm_secondary_ops->free_domain_ssid != NULL)
acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid);
ssid->secondary_ssid = NULL;
xfree(ssid);
printkd("%s: Freed individual domain ssid (domain=%02x).\n",__func__, id);
return ACM_OK;
}
+76
View File
@@ -0,0 +1,76 @@
/****************************************************************
* acm_null_hooks.c
*
* Copyright (C) 2005 IBM Corporation
*
* Author:
* Reiner Sailer <sailer@watson.ibm.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*/
#include <acm/acm_hooks.h>
static int
null_init_domain_ssid(void **chwall_ssid, ssidref_t ssidref)
{
return ACM_OK;
}
static void
null_free_domain_ssid(void *chwall_ssid)
{
return;
}
static int
null_dump_binary_policy(u8 *buf, u16 buf_size)
{
return 0;
}
static int
null_set_binary_policy(u8 *buf, u16 buf_size)
{
return -1;
}
static int
null_dump_stats(u8 *buf, u16 buf_size)
{
/* no stats for NULL policy */
return 0;
}
/* now define the hook structure similarly to LSM */
struct acm_operations acm_null_ops = {
.init_domain_ssid = null_init_domain_ssid,
.free_domain_ssid = null_free_domain_ssid,
.dump_binary_policy = null_dump_binary_policy,
.set_binary_policy = null_set_binary_policy,
.dump_statistics = null_dump_stats,
/* domain management control hooks */
.pre_domain_create = NULL,
.post_domain_create = NULL,
.fail_domain_create = NULL,
.post_domain_destroy = NULL,
/* event channel control hooks */
.pre_eventchannel_unbound = NULL,
.fail_eventchannel_unbound = NULL,
.pre_eventchannel_interdomain = NULL,
.fail_eventchannel_interdomain = NULL,
/* grant table control hooks */
.pre_grant_map_ref = NULL,
.fail_grant_map_ref = NULL,
.pre_grant_setup = NULL,
.fail_grant_setup = NULL
};
+197
View File
@@ -0,0 +1,197 @@
/****************************************************************
* acm_policy.c
*
* Copyright (C) 2005 IBM Corporation
*
* Author:
* Reiner Sailer <sailer@watson.ibm.com>
*
* Contributions:
* Stefan Berger <stefanb@watson.ibm.com>
* support for network-byte-order binary policies
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*
* sHype access control policy management for Xen.
* This interface allows policy tools in authorized
* domains to interact with the Xen access control module
*
*/
#include <xen/config.h>
#include <xen/errno.h>
#include <xen/types.h>
#include <xen/lib.h>
#include <xen/delay.h>
#include <xen/sched.h>
#include <public/policy_ops.h>
#include <acm/acm_core.h>
#include <acm/acm_hooks.h>
#include <acm/acm_endian.h>
int
acm_set_policy(void *buf, u16 buf_size, u16 policy)
{
u8 *policy_buffer = NULL;
struct acm_policy_buffer *pol;
if (policy != ACM_USE_SECURITY_POLICY) {
printk("%s: Loading incompatible policy (running: %s).\n", __func__,
ACM_POLICY_NAME(ACM_USE_SECURITY_POLICY));
return -EFAULT;
}
/* now check correct buffer sizes for policy combinations */
if (policy == ACM_NULL_POLICY) {
printkd("%s: NULL Policy, no policy needed.\n", __func__);
goto out;
}
if (buf_size < sizeof(struct acm_policy_buffer))
return -EFAULT;
/* 1. copy buffer from domain */
if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL)
goto error_free;
if (copy_from_user(policy_buffer, buf, buf_size)) {
printk("%s: Error copying!\n",__func__);
goto error_free;
}
/* 2. some sanity checking */
pol = (struct acm_policy_buffer *)policy_buffer;
if ((ntohl(pol->magic) != ACM_MAGIC) ||
(ntohs(pol->primary_policy_code) != acm_bin_pol.primary_policy_code) ||
(ntohs(pol->secondary_policy_code) != acm_bin_pol.secondary_policy_code)) {
printkd("%s: Wrong policy magics!\n", __func__);
goto error_free;
}
if (buf_size != ntohl(pol->len)) {
printk("%s: ERROR in buf size.\n", __func__);
goto error_free;
}
/* get bin_policy lock and rewrite policy (release old one) */
write_lock(&acm_bin_pol_rwlock);
/* 3. now get/set primary policy data */
if (acm_primary_ops->set_binary_policy(buf + ntohs(pol->primary_buffer_offset),
ntohs(pol->secondary_buffer_offset) -
ntohs(pol->primary_buffer_offset))) {
goto error_lock_free;
}
/* 4. now get/set secondary policy data */
if (acm_secondary_ops->set_binary_policy(buf + ntohs(pol->secondary_buffer_offset),
ntohl(pol->len) -
ntohs(pol->secondary_buffer_offset))) {
goto error_lock_free;
}
write_unlock(&acm_bin_pol_rwlock);
out:
printk("%s: Done .\n", __func__);
if (policy_buffer != NULL)
xfree(policy_buffer);
return ACM_OK;
error_lock_free:
write_unlock(&acm_bin_pol_rwlock);
error_free:
printk("%s: Error setting policy.\n", __func__);
if (policy_buffer != NULL)
xfree(policy_buffer);
return -ENOMEM;
}
int
acm_get_policy(void *buf, u16 buf_size)
{
u8 *policy_buffer;
int ret;
struct acm_policy_buffer *bin_pol;
if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL)
return -ENOMEM;
read_lock(&acm_bin_pol_rwlock);
/* future: read policy from file and set it */
bin_pol = (struct acm_policy_buffer *)policy_buffer;
bin_pol->magic = htonl(ACM_MAGIC);
bin_pol->policyversion = htonl(POLICY_INTERFACE_VERSION);
bin_pol->primary_policy_code = htons(acm_bin_pol.primary_policy_code);
bin_pol->secondary_policy_code = htons(acm_bin_pol.secondary_policy_code);
bin_pol->len = htonl(sizeof(struct acm_policy_buffer));
bin_pol->primary_buffer_offset = htons(ntohl(bin_pol->len));
bin_pol->secondary_buffer_offset = htons(ntohl(bin_pol->len));
ret = acm_primary_ops->dump_binary_policy (policy_buffer + ntohs(bin_pol->primary_buffer_offset),
buf_size - ntohs(bin_pol->primary_buffer_offset));
if (ret < 0) {
printk("%s: ERROR creating chwallpolicy buffer.\n", __func__);
read_unlock(&acm_bin_pol_rwlock);
return -1;
}
bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
bin_pol->secondary_buffer_offset = htons(ntohl(bin_pol->len));
ret = acm_secondary_ops->dump_binary_policy(policy_buffer + ntohs(bin_pol->secondary_buffer_offset),
buf_size - ntohs(bin_pol->secondary_buffer_offset));
if (ret < 0) {
printk("%s: ERROR creating chwallpolicy buffer.\n", __func__);
read_unlock(&acm_bin_pol_rwlock);
return -1;
}
bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
read_unlock(&acm_bin_pol_rwlock);
if (copy_to_user(buf, policy_buffer, ntohl(bin_pol->len)))
return -EFAULT;
xfree(policy_buffer);
return ACM_OK;
}
int
acm_dump_statistics(void *buf, u16 buf_size)
{
/* send stats to user space */
u8 *stats_buffer;
int len1, len2;
struct acm_stats_buffer acm_stats;
if ((stats_buffer = xmalloc_array(u8, buf_size)) == NULL)
return -ENOMEM;
read_lock(&acm_bin_pol_rwlock);
len1 = acm_primary_ops->dump_statistics(stats_buffer + sizeof(struct acm_stats_buffer),
buf_size - sizeof(struct acm_stats_buffer));
if (len1 < 0)
goto error_lock_free;
len2 = acm_secondary_ops->dump_statistics(stats_buffer + sizeof(struct acm_stats_buffer) + len1,
buf_size - sizeof(struct acm_stats_buffer) - len1);
if (len2 < 0)
goto error_lock_free;
acm_stats.magic = htonl(ACM_MAGIC);
acm_stats.policyversion = htonl(POLICY_INTERFACE_VERSION);
acm_stats.primary_policy_code = htons(acm_bin_pol.primary_policy_code);
acm_stats.secondary_policy_code = htons(acm_bin_pol.secondary_policy_code);
acm_stats.primary_stats_offset = htons(sizeof(struct acm_stats_buffer));
acm_stats.secondary_stats_offset = htons(sizeof(struct acm_stats_buffer) + len1);
acm_stats.len = htonl(sizeof(struct acm_stats_buffer) + len1 + len2);
memcpy(stats_buffer, &acm_stats, sizeof(struct acm_stats_buffer));
if (copy_to_user(buf, stats_buffer, sizeof(struct acm_stats_buffer) + len1 + len2))
goto error_lock_free;
read_unlock(&acm_bin_pol_rwlock);
xfree(stats_buffer);
return ACM_OK;
error_lock_free:
read_unlock(&acm_bin_pol_rwlock);
xfree(stats_buffer);
return -EFAULT;
}
/*eof*/
+638
View File
@@ -0,0 +1,638 @@
/****************************************************************
* acm_simple_type_enforcement_hooks.c
*
* Copyright (C) 2005 IBM Corporation
*
* Author:
* Reiner Sailer <sailer@watson.ibm.com>
*
* Contributors:
* Stefan Berger <stefanb@watson.ibm.com>
* support for network order binary policies
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*
* sHype Simple Type Enforcement for Xen
* STE allows to control which domains can setup sharing
* (eventchannels right now) with which other domains. Hooks
* are defined and called throughout Xen when domains bind to
* shared resources (setup eventchannels) and a domain is allowed
* to setup sharing with another domain if and only if both domains
* share at least on common type.
*
*/
#include <xen/lib.h>
#include <asm/types.h>
#include <asm/current.h>
#include <acm/acm_hooks.h>
#include <asm/atomic.h>
#include <acm/acm_endian.h>
/* local cache structures for chinese wall policy */
struct ste_binary_policy ste_bin_pol;
static inline int have_common_type (ssidref_t ref1, ssidref_t ref2) {
int i;
for(i=0; i< ste_bin_pol.max_types; i++)
if ( ste_bin_pol.ssidrefs[ref1*ste_bin_pol.max_types + i] &&
ste_bin_pol.ssidrefs[ref2*ste_bin_pol.max_types + i]) {
printkd("%s: common type #%02x.\n", __func__, i);
return 1;
}
return 0;
}
/* Helper function: return = (subj and obj share a common type) */
static int share_common_type(struct domain *subj, struct domain *obj)
{
ssidref_t ref_s, ref_o;
int ret;
if ((subj == NULL) || (obj == NULL) || (subj->ssid == NULL) || (obj->ssid == NULL))
return 0;
read_lock(&acm_bin_pol_rwlock);
/* lookup the policy-local ssids */
ref_s = ((struct ste_ssid *)(GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
(struct acm_ssid_domain *)subj->ssid)))->ste_ssidref;
ref_o = ((struct ste_ssid *)(GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
(struct acm_ssid_domain *)obj->ssid)))->ste_ssidref;
/* check whether subj and obj share a common ste type */
ret = have_common_type(ref_s, ref_o);
read_unlock(&acm_bin_pol_rwlock);
return ret;
}
/*
* Initializing chinese wall policy (will be filled by policy partition
* using setpolicy command)
*/
int acm_init_ste_policy(void)
{
/* minimal startup policy; policy write-locked already */
ste_bin_pol.max_types = 1;
ste_bin_pol.max_ssidrefs = 1;
ste_bin_pol.ssidrefs = (domaintype_t *)xmalloc_array(domaintype_t, 1);
if (ste_bin_pol.ssidrefs == NULL)
return ACM_INIT_SSID_ERROR;
/* initialize state */
ste_bin_pol.ssidrefs[0] = 1;
/* init stats */
atomic_set(&(ste_bin_pol.ec_eval_count), 0);
atomic_set(&(ste_bin_pol.ec_denied_count), 0);
atomic_set(&(ste_bin_pol.ec_cachehit_count), 0);
atomic_set(&(ste_bin_pol.gt_eval_count), 0);
atomic_set(&(ste_bin_pol.gt_denied_count), 0);
atomic_set(&(ste_bin_pol.gt_cachehit_count), 0);
return ACM_OK;
}
/* ste initialization function hooks */
static int
ste_init_domain_ssid(void **ste_ssid, ssidref_t ssidref)
{
int i;
struct ste_ssid *ste_ssidp = xmalloc(struct ste_ssid);
traceprintk("%s.\n", __func__);
if (ste_ssidp == NULL)
return ACM_INIT_SSID_ERROR;
/* get policy-local ssid reference */
ste_ssidp->ste_ssidref = GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref);
if (ste_ssidp->ste_ssidref >= ste_bin_pol.max_ssidrefs) {
printkd("%s: ERROR ste_ssidref (%x) > max(%x).\n",
__func__, ste_ssidp->ste_ssidref, ste_bin_pol.max_ssidrefs-1);
xfree(ste_ssidp);
return ACM_INIT_SSID_ERROR;
}
/* clean ste cache */
for (i=0; i<ACM_TE_CACHE_SIZE; i++)
ste_ssidp->ste_cache[i].valid = FREE;
(*ste_ssid) = ste_ssidp;
printkd("%s: determined ste_ssidref to %x.\n",
__func__, ste_ssidp->ste_ssidref);
return ACM_OK;
}
static void
ste_free_domain_ssid(void *ste_ssid)
{
traceprintk("%s.\n", __func__);
if (ste_ssid != NULL)
xfree(ste_ssid);
return;
}
/* dump type enforcement cache; policy read-locked already */
static int
ste_dump_policy(u8 *buf, u16 buf_size) {
struct acm_ste_policy_buffer *ste_buf = (struct acm_ste_policy_buffer *)buf;
int ret = 0;
ste_buf->ste_max_types = htons(ste_bin_pol.max_types);
ste_buf->ste_max_ssidrefs = htons(ste_bin_pol.max_ssidrefs);
ste_buf->policy_code = htons(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
ste_buf->ste_ssid_offset = htons(sizeof(struct acm_ste_policy_buffer));
ret = ntohs(ste_buf->ste_ssid_offset) +
sizeof(domaintype_t)*ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types;
/* now copy buffer over */
arrcpy(buf + ntohs(ste_buf->ste_ssid_offset),
ste_bin_pol.ssidrefs,
sizeof(domaintype_t),
ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types);
return ret;
}
/* ste_init_state is called when a policy is changed to detect violations (return != 0).
* from a security point of view, we simulate that all running domains are re-started and
* all sharing decisions are replayed to detect violations or current sharing behavior
* (right now: event_channels, future: also grant_tables)
*/
static int
ste_init_state(struct acm_ste_policy_buffer *ste_buf, domaintype_t *ssidrefs)
{
int violation = 1;
struct ste_ssid *ste_ssid, *ste_rssid;
ssidref_t ste_ssidref, ste_rssidref;
struct domain **pd, *rdom;
domid_t rdomid;
grant_entry_t sha_copy;
int port, i;
read_lock(&domlist_lock); /* go by domain? or directly by global? event/grant list */
/* go through all domains and adjust policy as if this domain was started now */
pd = &domain_list;
for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
(struct acm_ssid_domain *)(*pd)->ssid);
ste_ssidref = ste_ssid->ste_ssidref;
traceprintk("%s: validating policy for eventch domain %x (ste-Ref=%x).\n",
__func__, (*pd)->domain_id, ste_ssidref);
/* a) check for event channel conflicts */
for (port=0; port < NR_EVTCHN_BUCKETS; port++) {
spin_lock(&(*pd)->evtchn_lock);
if ((*pd)->evtchn[port] == NULL) {
spin_unlock(&(*pd)->evtchn_lock);
continue;
}
if ((*pd)->evtchn[port]->state == ECS_INTERDOMAIN) {
rdom = (*pd)->evtchn[port]->u.interdomain.remote_dom;
rdomid = rdom->domain_id;
/* rdom now has remote domain */
ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
(struct acm_ssid_domain *)(rdom->ssid));
ste_rssidref = ste_rssid->ste_ssidref;
} else if ((*pd)->evtchn[port]->state == ECS_UNBOUND) {
rdomid = (*pd)->evtchn[port]->u.unbound.remote_domid;
if ((rdom = find_domain_by_id(rdomid)) == NULL) {
printk("%s: Error finding domain to id %x!\n", __func__, rdomid);
goto out;
}
/* rdom now has remote domain */
ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
(struct acm_ssid_domain *)(rdom->ssid));
ste_rssidref = ste_rssid->ste_ssidref;
put_domain(rdom);
} else {
spin_unlock(&(*pd)->evtchn_lock);
continue; /* port unused */
}
spin_unlock(&(*pd)->evtchn_lock);
/* rdom now has remote domain */
ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
(struct acm_ssid_domain *)(rdom->ssid));
ste_rssidref = ste_rssid->ste_ssidref;
traceprintk("%s: eventch: domain %x (ssidref %x) --> domain %x (rssidref %x) used (port %x).\n",
__func__, (*pd)->domain_id, ste_ssidref, rdom->domain_id, ste_rssidref, port);
/* check whether on subj->ssid, obj->ssid share a common type*/
if (!have_common_type(ste_ssidref, ste_rssidref)) {
printkd("%s: Policy violation in event channel domain %x -> domain %x.\n",
__func__, (*pd)->domain_id, rdomid);
goto out;
}
}
/* b) check for grant table conflicts on shared pages */
if ((*pd)->grant_table->shared == NULL) {
printkd("%s: Grant ... sharing for domain %x not setup!\n", __func__, (*pd)->domain_id);
continue;
}
for ( i = 0; i < NR_GRANT_ENTRIES; i++ ) {
sha_copy = (*pd)->grant_table->shared[i];
if ( sha_copy.flags ) {
printkd("%s: grant dom (%hu) SHARED (%d) flags:(%hx) dom:(%hu) frame:(%lx)\n",
__func__, (*pd)->domain_id, i, sha_copy.flags, sha_copy.domid,
(unsigned long)sha_copy.frame);
rdomid = sha_copy.domid;
if ((rdom = find_domain_by_id(rdomid)) == NULL) {
printkd("%s: domain not found ERROR!\n", __func__);
goto out;
};
/* rdom now has remote domain */
ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
(struct acm_ssid_domain *)(rdom->ssid));
ste_rssidref = ste_rssid->ste_ssidref;
put_domain(rdom);
if (!have_common_type(ste_ssidref, ste_rssidref)) {
printkd("%s: Policy violation in grant table sharing domain %x -> domain %x.\n",
__func__, (*pd)->domain_id, rdomid);
goto out;
}
}
}
}
violation = 0;
out:
read_unlock(&domlist_lock);
return violation;
/* returning "violation != 0" means that existing sharing between domains would not
* have been allowed if the new policy had been enforced before the sharing; for ste,
* this means that there are at least 2 domains that have established sharing through
* event-channels or grant-tables but these two domains don't have no longer a common
* type in their typesets referenced by their ssidrefs */
}
/* set new policy; policy write-locked already */
static int
ste_set_policy(u8 *buf, u16 buf_size)
{
struct acm_ste_policy_buffer *ste_buf = (struct acm_ste_policy_buffer *)buf;
void *ssidrefsbuf;
struct ste_ssid *ste_ssid;
struct domain **pd;
int i;
/* Convert endianess of policy */
ste_buf->policy_code = ntohs(ste_buf->policy_code);
ste_buf->ste_max_types = ntohs(ste_buf->ste_max_types);
ste_buf->ste_max_ssidrefs = ntohs(ste_buf->ste_max_ssidrefs);
ste_buf->ste_ssid_offset = ntohs(ste_buf->ste_ssid_offset);
/* 1. create and copy-in new ssidrefs buffer */
ssidrefsbuf = xmalloc_array(u8, sizeof(domaintype_t)*ste_buf->ste_max_types*ste_buf->ste_max_ssidrefs);
if (ssidrefsbuf == NULL) {
return -ENOMEM;
}
if (ste_buf->ste_ssid_offset + sizeof(domaintype_t) * ste_buf->ste_max_ssidrefs*ste_buf->ste_max_types > buf_size)
goto error_free;
arrcpy(ssidrefsbuf,
buf + ste_buf->ste_ssid_offset,
sizeof(domaintype_t),
ste_buf->ste_max_ssidrefs*ste_buf->ste_max_types);
/* 2. now re-calculate sharing decisions based on running domains;
* this can fail if new policy is conflicting with sharing of running domains
* now: reject violating new policy; future: adjust sharing through revoking sharing */
if (ste_init_state(ste_buf, (domaintype_t *)ssidrefsbuf)) {
printk("%s: New policy conflicts with running domains. Policy load aborted.\n", __func__);
goto error_free; /* new policy conflicts with sharing of running domains */
}
/* 3. replace old policy (activate new policy) */
ste_bin_pol.max_types = ste_buf->ste_max_types;
ste_bin_pol.max_ssidrefs = ste_buf->ste_max_ssidrefs;
if (ste_bin_pol.ssidrefs)
xfree(ste_bin_pol.ssidrefs);
ste_bin_pol.ssidrefs = (domaintype_t *)ssidrefsbuf;
/* clear all ste caches */
read_lock(&domlist_lock);
pd = &domain_list;
for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
(struct acm_ssid_domain *)(*pd)->ssid);
for (i=0; i<ACM_TE_CACHE_SIZE; i++)
ste_ssid->ste_cache[i].valid = FREE;
}
read_unlock(&domlist_lock);
return ACM_OK;
error_free:
printk("%s: ERROR setting policy.\n", __func__);
if (ssidrefsbuf != NULL) xfree(ssidrefsbuf);
return -EFAULT;
}
static int
ste_dump_stats(u8 *buf, u16 buf_len)
{
struct acm_ste_stats_buffer stats;
#ifdef ACM_DEBUG
int i;
struct ste_ssid *ste_ssid;
struct domain **pd;
printk("ste: Decision caches:\n");
/* go through all domains and adjust policy as if this domain was started now */
read_lock(&domlist_lock); /* go by domain? or directly by global? event/grant list */
pd = &domain_list;
for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
printk("ste: Cache Domain %02x.\n", (*pd)->domain_id);
ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
(struct acm_ssid_domain *)(*pd)->ssid);
for (i=0; i<ACM_TE_CACHE_SIZE; i++)
printk("\t\tcache[%02x] = %s, domid=%x.\n", i,
(ste_ssid->ste_cache[i].valid == VALID) ?
"VALID" : "FREE",
(ste_ssid->ste_cache[i].valid == VALID) ?
ste_ssid->ste_cache[i].id : 0xffffffff);
}
read_unlock(&domlist_lock);
/* init stats */
printk("STE-Policy Security Hook Statistics:\n");
printk("ste: event_channel eval_count = %x\n", atomic_read(&(ste_bin_pol.ec_eval_count)));
printk("ste: event_channel denied_count = %x\n", atomic_read(&(ste_bin_pol.ec_denied_count)));
printk("ste: event_channel cache_hit_count = %x\n", atomic_read(&(ste_bin_pol.ec_cachehit_count)));
printk("ste:\n");
printk("ste: grant_table eval_count = %x\n", atomic_read(&(ste_bin_pol.gt_eval_count)));
printk("ste: grant_table denied_count = %x\n", atomic_read(&(ste_bin_pol.gt_denied_count)));
printk("ste: grant_table cache_hit_count = %x\n", atomic_read(&(ste_bin_pol.gt_cachehit_count)));
#endif
if (buf_len < sizeof(struct acm_ste_stats_buffer))
return -ENOMEM;
/* now send the hook counts to user space */
stats.ec_eval_count = htonl(atomic_read(&ste_bin_pol.ec_eval_count));
stats.gt_eval_count = htonl(atomic_read(&ste_bin_pol.gt_eval_count));
stats.ec_denied_count = htonl(atomic_read(&ste_bin_pol.ec_denied_count));
stats.gt_denied_count = htonl(atomic_read(&ste_bin_pol.gt_denied_count));
stats.ec_cachehit_count = htonl(atomic_read(&ste_bin_pol.ec_cachehit_count));
stats.gt_cachehit_count = htonl(atomic_read(&ste_bin_pol.gt_cachehit_count));
memcpy(buf, &stats, sizeof(struct acm_ste_stats_buffer));
return sizeof(struct acm_ste_stats_buffer);
}
/* we need to go through this before calling the hooks,
* returns 1 == cache hit */
static int inline
check_cache(struct domain *dom, domid_t rdom) {
struct ste_ssid *ste_ssid;
int i;
printkd("checking cache: %x --> %x.\n", dom->domain_id, rdom);
ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
(struct acm_ssid_domain *)(dom)->ssid);
for(i=0; i< ACM_TE_CACHE_SIZE; i++) {
if ((ste_ssid->ste_cache[i].valid == VALID) &&
(ste_ssid->ste_cache[i].id == rdom)) {
printkd("cache hit (entry %x, id= %x!\n", i, ste_ssid->ste_cache[i].id);
return 1;
}
}
return 0;
}
/* we only get here if there is NO entry yet; no duplication check! */
static void inline
cache_result(struct domain *subj, struct domain *obj) {
struct ste_ssid *ste_ssid;
int i;
printkd("caching from doms: %x --> %x.\n", subj->domain_id, obj->domain_id);
ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
(struct acm_ssid_domain *)(subj)->ssid);
for(i=0; i< ACM_TE_CACHE_SIZE; i++)
if (ste_ssid->ste_cache[i].valid == FREE)
break;
if (i< ACM_TE_CACHE_SIZE) {
ste_ssid->ste_cache[i].valid = VALID;
ste_ssid->ste_cache[i].id = obj->domain_id;
} else
printk ("Cache of dom %x is full!\n", subj->domain_id);
}
/* deletes entries for domain 'id' from all caches (re-use) */
static void inline
clean_id_from_cache(domid_t id)
{
struct ste_ssid *ste_ssid;
int i;
struct domain **pd;
printkd("deleting cache for dom %x.\n", id);
read_lock(&domlist_lock); /* look through caches of all domains */
pd = &domain_list;
for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
(struct acm_ssid_domain *)(*pd)->ssid);
for (i=0; i<ACM_TE_CACHE_SIZE; i++)
if ((ste_ssid->ste_cache[i].valid == VALID) &&
(ste_ssid->ste_cache[i].id = id))
ste_ssid->ste_cache[i].valid = FREE;
}
read_unlock(&domlist_lock);
}
/***************************
* Authorization functions
**************************/
static int
ste_pre_domain_create(void *subject_ssid, ssidref_t ssidref)
{
/* check for ssidref in range for policy */
ssidref_t ste_ssidref;
traceprintk("%s.\n", __func__);
read_lock(&acm_bin_pol_rwlock);
ste_ssidref = GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref);
if (ste_ssidref == ACM_DEFAULT_LOCAL_SSID) {
printk("%s: ERROR STE SSID is NOT SET but policy enforced.\n", __func__);
read_unlock(&acm_bin_pol_rwlock);
return ACM_ACCESS_DENIED; /* catching and indicating config error */
}
if (ste_ssidref >= ste_bin_pol.max_ssidrefs) {
printk("%s: ERROR ste_ssidref > max(%x).\n",
__func__, ste_bin_pol.max_ssidrefs-1);
read_unlock(&acm_bin_pol_rwlock);
return ACM_ACCESS_DENIED;
}
read_unlock(&acm_bin_pol_rwlock);
return ACM_ACCESS_PERMITTED;
}
static void
ste_post_domain_destroy(void *subject_ssid, domid_t id)
{
/* clean all cache entries for destroyed domain (might be re-used) */
clean_id_from_cache(id);
}
/* -------- EVENTCHANNEL OPERATIONS -----------*/
static int
ste_pre_eventchannel_unbound(domid_t id) {
struct domain *subj, *obj;
int ret;
traceprintk("%s: dom%x-->dom%x.\n",
__func__, current->domain->domain_id, id);
if (check_cache(current->domain, id)) {
atomic_inc(&ste_bin_pol.ec_cachehit_count);
return ACM_ACCESS_PERMITTED;
}
atomic_inc(&ste_bin_pol.ec_eval_count);
subj = current->domain;
obj = find_domain_by_id(id);
if (share_common_type(subj, obj)) {
cache_result(subj, obj);
ret = ACM_ACCESS_PERMITTED;
} else {
atomic_inc(&ste_bin_pol.ec_denied_count);
ret = ACM_ACCESS_DENIED;
}
if (obj != NULL)
put_domain(obj);
return ret;
}
static int
ste_pre_eventchannel_interdomain(domid_t id1, domid_t id2)
{
struct domain *subj, *obj;
int ret;
traceprintk("%s: dom%x-->dom%x.\n", __func__,
(id1 == DOMID_SELF) ? current->domain->domain_id : id1,
(id2 == DOMID_SELF) ? current->domain->domain_id : id2);
/* following is a bit longer but ensures that we
* "put" only domains that we where "find"-ing
*/
if (id1 == DOMID_SELF) id1 = current->domain->domain_id;
if (id2 == DOMID_SELF) id2 = current->domain->domain_id;
subj = find_domain_by_id(id1);
obj = find_domain_by_id(id2);
if ((subj == NULL) || (obj == NULL)) {
ret = ACM_ACCESS_DENIED;
goto out;
}
/* cache check late, but evtchn is not on performance critical path */
if (check_cache(subj, obj->domain_id)) {
atomic_inc(&ste_bin_pol.ec_cachehit_count);
ret = ACM_ACCESS_PERMITTED;
goto out;
}
atomic_inc(&ste_bin_pol.ec_eval_count);
if (share_common_type(subj, obj)) {
cache_result(subj, obj);
ret = ACM_ACCESS_PERMITTED;
} else {
atomic_inc(&ste_bin_pol.ec_denied_count);
ret = ACM_ACCESS_DENIED;
}
out:
if (obj != NULL)
put_domain(obj);
if (subj != NULL)
put_domain(subj);
return ret;
}
/* -------- SHARED MEMORY OPERATIONS -----------*/
static int
ste_pre_grant_map_ref (domid_t id) {
struct domain *obj, *subj;
int ret;
traceprintk("%s: dom%x-->dom%x.\n", __func__,
current->domain->domain_id, id);
if (check_cache(current->domain, id)) {
atomic_inc(&ste_bin_pol.gt_cachehit_count);
return ACM_ACCESS_PERMITTED;
}
atomic_inc(&ste_bin_pol.gt_eval_count);
subj = current->domain;
obj = find_domain_by_id(id);
if (share_common_type(subj, obj)) {
cache_result(subj, obj);
ret = ACM_ACCESS_PERMITTED;
} else {
atomic_inc(&ste_bin_pol.gt_denied_count);
printkd("%s: ACCESS DENIED!\n", __func__);
ret = ACM_ACCESS_DENIED;
}
if (obj != NULL)
put_domain(obj);
return ret;
}
/* since setting up grant tables involves some implicit information
flow from the creating domain to the domain that is setup, we
check types in addition to the general authorization */
static int
ste_pre_grant_setup (domid_t id) {
struct domain *obj, *subj;
int ret;
traceprintk("%s: dom%x-->dom%x.\n", __func__,
current->domain->domain_id, id);
if (check_cache(current->domain, id)) {
atomic_inc(&ste_bin_pol.gt_cachehit_count);
return ACM_ACCESS_PERMITTED;
}
atomic_inc(&ste_bin_pol.gt_eval_count);
/* a) check authorization (eventually use specific capabilities) */
if (!IS_PRIV(current->domain)) {
printk("%s: Grant table management authorization denied ERROR!\n", __func__);
return ACM_ACCESS_DENIED;
}
/* b) check types */
subj = current->domain;
obj = find_domain_by_id(id);
if (share_common_type(subj, obj)) {
cache_result(subj, obj);
ret = ACM_ACCESS_PERMITTED;
} else {
atomic_inc(&ste_bin_pol.gt_denied_count);
ret = ACM_ACCESS_DENIED;
}
if (obj != NULL)
put_domain(obj);
return ret;
}
/* now define the hook structure similarly to LSM */
struct acm_operations acm_simple_type_enforcement_ops = {
/* policy management services */
.init_domain_ssid = ste_init_domain_ssid,
.free_domain_ssid = ste_free_domain_ssid,
.dump_binary_policy = ste_dump_policy,
.set_binary_policy = ste_set_policy,
.dump_statistics = ste_dump_stats,
/* domain management control hooks */
.pre_domain_create = ste_pre_domain_create,
.post_domain_create = NULL,
.fail_domain_create = NULL,
.post_domain_destroy = ste_post_domain_destroy,
/* event channel control hooks */
.pre_eventchannel_unbound = ste_pre_eventchannel_unbound,
.fail_eventchannel_unbound = NULL,
.pre_eventchannel_interdomain = ste_pre_eventchannel_interdomain,
.fail_eventchannel_interdomain = NULL,
/* grant table control hooks */
.pre_grant_map_ref = ste_pre_grant_map_ref,
.fail_grant_map_ref = NULL,
.pre_grant_setup = ste_pre_grant_setup,
.fail_grant_setup = NULL,
};
+1 -1
View File
@@ -15,7 +15,7 @@ OBJS = xensetup.o setup.o time.o irq.o ia64_ksyms.o process.o smp.o \
ifeq ($(CONFIG_VTI),y)
OBJS += vmx_init.o vmx_virt.o vmx_vcpu.o vmx_process.o vmx_vsa.o vmx_ivt.o \
vmx_phy_mode.o vmx_utility.o vmx_interrupt.o vmx_entry.o vmmu.o \
vtlb.o mmio.o vlsapic.o
vtlb.o mmio.o vlsapic.o vmx_hypercall.o mm.o
endif
# perfmon.o
# unwind.o needed for kernel unwinding (rare)
+3
View File
@@ -75,6 +75,9 @@ void foo(void)
DEFINE(IA64_VCPU_META_SAVED_RR0_OFFSET, offsetof (struct vcpu, arch.metaphysical_saved_rr0));
DEFINE(IA64_VCPU_BREAKIMM_OFFSET, offsetof (struct vcpu, arch.breakimm));
DEFINE(IA64_VCPU_IVA_OFFSET, offsetof (struct vcpu, arch.iva));
DEFINE(IA64_VCPU_IRR0_OFFSET, offsetof (struct vcpu, arch.irr[0]));
DEFINE(IA64_VCPU_IRR3_OFFSET, offsetof (struct vcpu, arch.irr[3]));
DEFINE(IA64_VCPU_INSVC3_OFFSET, offsetof (struct vcpu, arch.insvc[3]));
BLANK();
+43 -15
View File
@@ -18,14 +18,6 @@
#include <xen/console.h>
#include <public/sched_ctl.h>
#define TRC_DOM0OP_ENTER_BASE 0x00020000
#define TRC_DOM0OP_LEAVE_BASE 0x00030000
static int msr_cpu_mask;
static unsigned long msr_addr;
static unsigned long msr_lo;
static unsigned long msr_hi;
long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
{
long ret = 0;
@@ -35,6 +27,49 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
switch ( op->cmd )
{
/*
* NOTE: DOM0_GETMEMLIST has somewhat different semantics on IA64 -
* it actually allocates and maps pages.
*/
case DOM0_GETMEMLIST:
{
unsigned long i;
struct domain *d = find_domain_by_id(op->u.getmemlist.domain);
unsigned long start_page = op->u.getmemlist.max_pfns >> 32;
unsigned long nr_pages = op->u.getmemlist.max_pfns & 0xffffffff;
unsigned long pfn;
unsigned long *buffer = op->u.getmemlist.buffer;
struct page *page;
ret = -EINVAL;
if ( d != NULL )
{
ret = 0;
for ( i = start_page; i < (start_page + nr_pages); i++ )
{
page = map_new_domain_page(d, i << PAGE_SHIFT);
if ( page == NULL )
{
ret = -ENOMEM;
break;
}
pfn = page_to_pfn(page);
if ( put_user(pfn, buffer) )
{
ret = -EFAULT;
break;
}
buffer++;
}
op->u.getmemlist.num_pfns = i - start_page;
copy_to_user(u_dom0_op, op, sizeof(*op));
put_domain(d);
}
}
break;
default:
ret = -ENOSYS;
@@ -43,10 +78,3 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
return ret;
}
void arch_getdomaininfo_ctxt(struct domain *d, struct vcpu_guest_context *c)
{
int i;
dummy();
}
+96 -130
View File
@@ -76,7 +76,7 @@ extern unsigned long dom_fw_setup(struct domain *, char *, int);
/* this belongs in include/asm, but there doesn't seem to be a suitable place */
void free_perdomain_pt(struct domain *d)
{
dummy();
printf("free_perdomain_pt: not implemented\n");
//free_page((unsigned long)d->mm.perdomain_pt);
}
@@ -166,27 +166,49 @@ void arch_free_vcpu_struct(struct vcpu *v)
free_xenheap_pages(v, KERNEL_STACK_SIZE_ORDER);
}
static void init_switch_stack(struct vcpu *v)
{
struct pt_regs *regs = (struct pt_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1;
struct switch_stack *sw = (struct switch_stack *) regs - 1;
extern void ia64_ret_from_clone;
memset(sw, 0, sizeof(struct switch_stack) + sizeof(struct pt_regs));
sw->ar_bspstore = (unsigned long)v + IA64_RBS_OFFSET;
sw->b0 = (unsigned long) &ia64_ret_from_clone;
sw->ar_fpsr = FPSR_DEFAULT;
v->arch._thread.ksp = (unsigned long) sw - 16;
// stay on kernel stack because may get interrupts!
// ia64_ret_from_clone (which b0 gets in new_thread) switches
// to user stack
v->arch._thread.on_ustack = 0;
memset(v->arch._thread.fph,0,sizeof(struct ia64_fpreg)*96);
}
#ifdef CONFIG_VTI
void arch_do_createdomain(struct vcpu *v)
{
struct domain *d = v->domain;
struct thread_info *ti = alloc_thread_info(v);
/* If domain is VMX domain, shared info area is created
* by domain and then domain notifies HV by specific hypercall.
* If domain is xenolinux, shared info area is created by
* HV.
* Since we have no idea about whether domain is VMX now,
* (dom0 when parse and domN when build), postpone possible
* allocation.
*/
/* Clear thread_info to clear some important fields, like preempt_count */
memset(ti, 0, sizeof(struct thread_info));
init_switch_stack(v);
/* Shared info area is required to be allocated at domain
* creation, since control panel will write some I/O info
* between front end and back end to that area. However for
* vmx domain, our design is to let domain itself to allcoate
* shared info area, to keep machine page contiguous. So this
* page will be released later when domainN issues request
* after up.
*/
d->shared_info = (void *)alloc_xenheap_page();
/* FIXME: Because full virtual cpu info is placed in this area,
* it's unlikely to put it into one shareinfo page. Later
* need split vcpu context from vcpu_info and conforms to
* normal xen convention.
*/
d->shared_info = NULL;
v->vcpu_info = (void *)alloc_xenheap_page();
if (!v->vcpu_info) {
printk("ERROR/HALTING: CAN'T ALLOC PAGE\n");
@@ -194,9 +216,6 @@ void arch_do_createdomain(struct vcpu *v)
}
memset(v->vcpu_info, 0, PAGE_SIZE);
/* Clear thread_info to clear some important fields, like preempt_count */
memset(ti, 0, sizeof(struct thread_info));
/* Allocate per-domain vTLB and vhpt */
v->arch.vtlb = init_domain_tlb(v);
@@ -211,38 +230,25 @@ void arch_do_createdomain(struct vcpu *v)
d->xen_vastart = 0xf000000000000000;
d->xen_vaend = 0xf300000000000000;
d->arch.breakimm = 0x1000;
// stay on kernel stack because may get interrupts!
// ia64_ret_from_clone (which b0 gets in new_thread) switches
// to user stack
v->arch._thread.on_ustack = 0;
}
#else // CONFIG_VTI
void arch_do_createdomain(struct vcpu *v)
{
struct domain *d = v->domain;
struct thread_info *ti = alloc_thread_info(v);
/* Clear thread_info to clear some important fields, like preempt_count */
memset(ti, 0, sizeof(struct thread_info));
init_switch_stack(v);
d->shared_info = (void *)alloc_xenheap_page();
v->vcpu_info = (void *)alloc_xenheap_page();
if (!v->vcpu_info) {
if (!d->shared_info) {
printk("ERROR/HALTING: CAN'T ALLOC PAGE\n");
while (1);
}
memset(v->vcpu_info, 0, PAGE_SIZE);
/* pin mapping */
// FIXME: Does this belong here? Or do only at domain switch time?
#if 0
// this is now done in ia64_new_rr7
{
/* WARNING: following must be inlined to avoid nested fault */
unsigned long psr = ia64_clear_ic();
ia64_itr(0x2, IA64_TR_SHARED_INFO, SHAREDINFO_ADDR,
pte_val(pfn_pte(ia64_tpa(d->shared_info) >> PAGE_SHIFT, PAGE_KERNEL)),
PAGE_SHIFT);
ia64_set_psr(psr);
ia64_srlz_i();
}
#endif
memset(d->shared_info, 0, PAGE_SIZE);
v->vcpu_info = &(d->shared_info->vcpu_data[0]);
d->max_pages = (128*1024*1024)/PAGE_SIZE; // 128MB default // FIXME
if ((d->arch.metaphysical_rr0 = allocate_metaphysical_rr0()) == -1UL)
BUG();
@@ -258,33 +264,63 @@ void arch_do_createdomain(struct vcpu *v)
d->shared_info_va = 0xf100000000000000;
d->arch.breakimm = 0x1000;
v->arch.breakimm = d->arch.breakimm;
// stay on kernel stack because may get interrupts!
// ia64_ret_from_clone (which b0 gets in new_thread) switches
// to user stack
v->arch._thread.on_ustack = 0;
d->arch.mm = xmalloc(struct mm_struct);
if (unlikely(!d->arch.mm)) {
printk("Can't allocate mm_struct for domain %d\n",d->domain_id);
return -ENOMEM;
}
memset(d->arch.mm, 0, sizeof(*d->arch.mm));
d->arch.mm->pgd = pgd_alloc(d->arch.mm);
if (unlikely(!d->arch.mm->pgd)) {
printk("Can't allocate pgd for domain %d\n",d->domain_id);
return -ENOMEM;
}
}
#endif // CONFIG_VTI
void arch_do_boot_vcpu(struct vcpu *v)
void arch_getdomaininfo_ctxt(struct vcpu *v, struct vcpu_guest_context *c)
{
return;
struct pt_regs *regs = (struct pt_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1;
printf("arch_getdomaininfo_ctxt\n");
c->regs = *regs;
c->vcpu = v->vcpu_info->arch;
c->shared = v->domain->shared_info->arch;
}
int arch_set_info_guest(struct vcpu *v, struct vcpu_guest_context *c)
{
dummy();
return 1;
struct pt_regs *regs = (struct pt_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1;
printf("arch_set_info_guest\n");
*regs = c->regs;
regs->cr_ipsr = IA64_PSR_IT|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_IC|IA64_PSR_I|IA64_PSR_DFH|IA64_PSR_BN|IA64_PSR_SP|IA64_PSR_DI;
regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT;
regs->ar_rsc |= (2 << 2); /* force PL2/3 */
v->vcpu_info->arch = c->vcpu;
init_all_rr(v);
// this should be in userspace
regs->r28 = dom_fw_setup(v->domain,"nomca nosmp xencons=ttyS console=ttyS0",256L); //FIXME
v->vcpu_info->arch.banknum = 1;
v->vcpu_info->arch.metaphysical_mode = 1;
v->domain->shared_info->arch = c->shared;
return 0;
}
int arch_final_setup_guest(struct vcpu *v, struct vcpu_guest_context *c)
void arch_do_boot_vcpu(struct vcpu *v)
{
dummy();
return 1;
printf("arch_do_boot_vcpu: not implemented\n");
return;
}
void domain_relinquish_resources(struct domain *d)
{
dummy();
/* FIXME */
printf("domain_relinquish_resources: not implemented\n");
}
#ifdef CONFIG_VTI
@@ -294,10 +330,8 @@ void new_thread(struct vcpu *v,
unsigned long start_info)
{
struct domain *d = v->domain;
struct switch_stack *sw;
struct xen_regs *regs;
struct ia64_boot_param *bp;
extern char ia64_ret_from_clone;
extern char saved_command_line[];
//char *dom0_cmdline = "BOOT_IMAGE=scsi0:\EFI\redhat\xenlinux nomca root=/dev/sdb1 ro";
@@ -305,11 +339,8 @@ void new_thread(struct vcpu *v,
#ifdef CONFIG_DOMAIN0_CONTIGUOUS
if (d == dom0) start_pc += dom0_start;
#endif
regs = (struct xen_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1;
sw = (struct switch_stack *) regs - 1;
/* Sanity Clear */
memset(sw, 0, sizeof(struct xen_regs) + sizeof(struct switch_stack));
regs = (struct pt_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1;
if (VMX_DOMAIN(v)) {
/* dt/rt/it:1;i/ic:1, si:1, vm/bn:1, ac:1 */
regs->cr_ipsr = 0x501008826008; /* Need to be expanded as macro */
@@ -320,33 +351,23 @@ void new_thread(struct vcpu *v,
regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT; // domain runs at PL2
}
regs->cr_iip = start_pc;
regs->ar_rsc = 0x0;
regs->cr_ifs = 0x0;
regs->ar_fpsr = sw->ar_fpsr = FPSR_DEFAULT;
sw->ar_bspstore = (unsigned long)v + IA64_RBS_OFFSET;
printf("new_thread: v=%p, regs=%p, sw=%p, new_rbs=%p, IA64_STK_OFFSET=%p, &r8=%p\n",
v,regs,sw,sw->ar_bspstore,IA64_STK_OFFSET,&regs->r8);
printf("iip:0x%lx,ipsr:0x%lx\n", regs->cr_iip, regs->cr_ipsr);
sw->b0 = (unsigned long) &ia64_ret_from_clone;
v->arch._thread.ksp = (unsigned long) sw - 16;
printk("new_thread, about to call init_all_rr\n");
regs->cr_ifs = 0; /* why? - matthewc */
regs->ar_fpsr = FPSR_DEFAULT;
if (VMX_DOMAIN(v)) {
vmx_init_all_rr(v);
} else
init_all_rr(v);
// set up boot parameters (and fake firmware)
printk("new_thread, about to call dom_fw_setup\n");
VMX_VPD(v,vgr[12]) = dom_fw_setup(d,saved_command_line,256L); //FIXME
printk("new_thread, done with dom_fw_setup\n");
if (VMX_DOMAIN(v)) {
VMX_VPD(v,vgr[12]) = dom_fw_setup(d,saved_command_line,256L);
/* Virtual processor context setup */
VMX_VPD(v, vpsr) = IA64_PSR_BN;
VPD_CR(v, dcr) = 0;
} else {
// don't forget to set this!
regs->r28 = dom_fw_setup(d,saved_command_line,256L);
v->vcpu_info->arch.banknum = 1;
v->vcpu_info->arch.metaphysical_mode = 1;
d->shared_info->arch.flags = (d == dom0) ? (SIF_INITDOMAIN|SIF_PRIVILEGED|SIF_BLK_BE_DOMAIN|SIF_NET_BE_DOMAIN|SIF_USB_BE_DOMAIN) : 0;
}
}
#else // CONFIG_VTI
@@ -359,54 +380,27 @@ void new_thread(struct vcpu *v,
unsigned long start_info)
{
struct domain *d = v->domain;
struct switch_stack *sw;
struct pt_regs *regs;
unsigned long new_rbs;
struct ia64_boot_param *bp;
extern char ia64_ret_from_clone;
extern char saved_command_line[];
#ifdef CONFIG_DOMAIN0_CONTIGUOUS
if (d == dom0) start_pc += dom0_start;
#endif
regs = (struct pt_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1;
sw = (struct switch_stack *) regs - 1;
memset(sw,0,sizeof(struct switch_stack)+sizeof(struct pt_regs));
new_rbs = (unsigned long) v + IA64_RBS_OFFSET;
regs->cr_ipsr = ia64_getreg(_IA64_REG_PSR)
| IA64_PSR_BITS_TO_SET | IA64_PSR_BN
& ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_RI | IA64_PSR_IS);
regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT; // domain runs at PL2
regs->cr_iip = start_pc;
regs->ar_rsc = 0; /* lazy mode */
regs->ar_rnat = 0;
regs->ar_fpsr = sw->ar_fpsr = FPSR_DEFAULT;
regs->loadrs = 0;
//regs->r8 = current->mm->dumpable; /* set "don't zap registers" flag */
//regs->r8 = 0x01234567890abcdef; // FIXME: temp marker
//regs->r12 = ((unsigned long) regs - 16); /* 16 byte scratch */
regs->cr_ifs = 1UL << 63;
regs->pr = 0;
sw->pr = 0;
regs->ar_pfs = 0;
sw->caller_unat = 0;
sw->ar_pfs = 0;
sw->ar_bspstore = new_rbs;
//regs->r13 = (unsigned long) v;
printf("new_thread: v=%p, start_pc=%p, regs=%p, sw=%p, new_rbs=%p, IA64_STK_OFFSET=%p, &r8=%p\n",
v,start_pc,regs,sw,new_rbs,IA64_STK_OFFSET,&regs->r8);
sw->b0 = (unsigned long) &ia64_ret_from_clone;
v->arch._thread.ksp = (unsigned long) sw - 16;
//v->thread_info->flags = 0;
printk("new_thread, about to call init_all_rr\n");
regs->ar_fpsr = FPSR_DEFAULT;
init_all_rr(v);
// set up boot parameters (and fake firmware)
printk("new_thread, about to call dom_fw_setup\n");
regs->r28 = dom_fw_setup(d,saved_command_line,256L); //FIXME
printk("new_thread, done with dom_fw_setup\n");
// don't forget to set this!
v->vcpu_info->arch.banknum = 1;
memset(v->arch._thread.fph,0,sizeof(struct ia64_fpreg)*96);
v->vcpu_info->arch.metaphysical_mode = 1;
d->shared_info->arch.flags = (d == dom0) ? (SIF_INITDOMAIN|SIF_PRIVILEGED|SIF_BLK_BE_DOMAIN|SIF_NET_BE_DOMAIN|SIF_USB_BE_DOMAIN) : 0;
}
#endif // CONFIG_VTI
@@ -1037,21 +1031,6 @@ int construct_dom0(struct domain *d,
strcpy(d->name,"Domain0");
#endif
// prepare domain0 pagetable (maps METAphysical to physical)
// following is roughly mm_init() in linux/kernel/fork.c
d->arch.mm = xmalloc(struct mm_struct);
if (unlikely(!d->arch.mm)) {
printk("Can't allocate mm_struct for domain0\n");
return -ENOMEM;
}
memset(d->arch.mm, 0, sizeof(*d->arch.mm));
d->arch.mm->pgd = pgd_alloc(d->arch.mm);
if (unlikely(!d->arch.mm->pgd)) {
printk("Can't allocate pgd for domain0\n");
return -ENOMEM;
}
/* Mask all upcalls... */
for ( i = 0; i < MAX_VIRT_CPUS; i++ )
d->shared_info->vcpu_data[i].evtchn_upcall_mask = 1;
@@ -1146,19 +1125,6 @@ int construct_domU(struct domain *d,
printk("parsedomainelfimage returns %d\n",rc);
if ( rc != 0 ) return rc;
d->arch.mm = xmalloc(struct mm_struct);
if (unlikely(!d->arch.mm)) {
printk("Can't allocate mm_struct for domain %d\n",d->domain_id);
return -ENOMEM;
}
memset(d->arch.mm, 0, sizeof(*d->arch.mm));
d->arch.mm->pgd = pgd_alloc(d->arch.mm);
if (unlikely(!d->arch.mm->pgd)) {
printk("Can't allocate pgd for domain %d\n",d->domain_id);
return -ENOMEM;
}
/* Mask all upcalls... */
for ( i = 0; i < MAX_VIRT_CPUS; i++ )
d->shared_info->vcpu_data[i].evtchn_upcall_mask = 1;
@@ -1231,10 +1197,10 @@ void machine_halt(void)
while(1);
}
void dummy(void)
void dummy_called(char *function)
{
if (platform_is_hp_ski()) asm("break 0;;");
printf("dummy called: spinning....\n");
printf("dummy called in %s: spinning....\n", function);
while(1);
}
+25 -2
View File
@@ -19,8 +19,6 @@ extern unsigned long translate_domain_mpaddr(unsigned long);
extern struct ia64_sal_retval pal_emulator_static(UINT64);
extern struct ia64_sal_retval sal_emulator(UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64);
void fooefi(void) {}
int
ia64_hypercall (struct pt_regs *regs)
{
@@ -122,6 +120,31 @@ ia64_hypercall (struct pt_regs *regs)
case 0xfffb: // test dummy hypercall
regs->r8 = domU_staging_read_8(vcpu_get_gr(v,32));
break;
case __HYPERVISOR_dom0_op:
regs->r8 = do_dom0_op(regs->r14);
break;
case __HYPERVISOR_dom_mem_op:
#ifdef CONFIG_VTI
regs->r8 = do_dom_mem_op(regs->r14, regs->r15, regs->r16, regs->r17, regs->r18);
#else
/* we don't handle reservations; just return success */
regs->r8 = regs->r16;
#endif
break;
case __HYPERVISOR_event_channel_op:
regs->r8 = do_event_channel_op(regs->r14);
break;
case __HYPERVISOR_console_io:
regs->r8 = do_console_io(regs->r14, regs->r15, regs->r16);
break;
default:
printf("unknown hypercall %x\n", regs->r2);
regs->r8 = (unsigned long)-1;
}
return 1;
}
+35 -19
View File
@@ -41,40 +41,46 @@
// r19 == vpsr.ic (low 32 bits) | vpsr.i (high 32 bits)
// r31 == pr
GLOBAL_ENTRY(fast_hyperprivop)
#if 1
// HYPERPRIVOP_SSM_I?
// assumes domain interrupts pending, so just do it
cmp.eq p7,p6=XEN_HYPER_SSM_I,r17
(p7) br.sptk.many hyper_ssm_i;;
#endif
#if 1
// if domain interrupts pending, give up for now and do it the slow way
// FIXME. This algorithm gives up (goes to the slow path) if there
// are ANY interrupts pending, even if they are currently
// undeliverable. This should be improved later...
adds r20=XSI_PEND_OFS-XSI_PSR_IC_OFS,r18 ;;
ld8 r20=[r20] ;;
cmp.ne p7,p0=r0,r20
(p7) br.sptk.many dispatch_break_fault ;;
ld4 r20=[r20] ;;
cmp.eq p7,p0=r0,r20
(p7) br.cond.sptk.many 1f
mov r20=IA64_KR(CURRENT);;
adds r21=IA64_VCPU_IRR0_OFFSET,r20;
adds r22=IA64_VCPU_IRR0_OFFSET+8,r20;;
ld8 r23=[r21],16; ld8 r24=[r22],16;;
ld8 r21=[r21]; ld8 r22=[r22];;
or r23=r23,r24; or r21=r21,r22;;
or r20=r23,r21;;
1: // when we get to here r20=~=interrupts pending
// HYPERPRIVOP_RFI?
cmp.eq p7,p6=XEN_HYPER_RFI,r17
(p7) br.sptk.many hyper_rfi;;
cmp.ne p7,p0=r20,r0
(p7) br.spnt.many dispatch_break_fault ;;
// hard to test, because only called from rbs_switch
// HYPERPRIVOP_COVER?
cmp.eq p7,p6=XEN_HYPER_COVER,r17
(p7) br.sptk.many hyper_cover;;
#endif
#if 1
// HYPERPRIVOP_SSM_DT?
cmp.eq p7,p6=XEN_HYPER_SSM_DT,r17
(p7) br.sptk.many hyper_ssm_dt;;
#endif
#if 1
// HYPERPRIVOP_RSM_DT?
cmp.eq p7,p6=XEN_HYPER_RSM_DT,r17
(p7) br.sptk.many hyper_rsm_dt;;
#endif
// if not one of the above, give up for now and do it the slow way
br.sptk.many dispatch_break_fault ;;
@@ -336,12 +342,16 @@ GLOBAL_ENTRY(fast_break_reflect)
// ensure that, if giving up, registers at entry to fast_hyperprivop unchanged
ENTRY(hyper_rfi)
#ifdef FAST_HYPERPRIVOP_CNT
movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_RFI);;
ld8 r21=[r20];;
adds r21=1,r21;;
st8 [r20]=r21;;
#endif
// if no interrupts pending, proceed
cmp.eq p7,p0=r20,r0
(p7) br.sptk.many 1f
// interrupts pending, if rfi'ing to interrupts on, go slow way
adds r20=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 ;;
ld8 r21=[r20];; // r21 = vcr.ipsr
extr.u r22=r21,IA64_PSR_I_BIT,1 ;;
cmp.ne p7,p0=r22,r0 ;;
(p7) br.spnt.many dispatch_break_fault ;;
1:
adds r20=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 ;;
ld8 r21=[r20];; // r21 = vcr.ipsr
extr.u r22=r21,IA64_PSR_BE_BIT,1 ;;
@@ -375,7 +385,13 @@ ENTRY(hyper_rfi)
(p7) br.sptk.many dispatch_break_fault ;;
// OK now, let's do an rfi.
// r18=&vpsr.i|vpsr.ic, r21==vpsr, r20==&vcr.iip, r22=vcr.iip
#ifdef FAST_HYPERPRIVOP_CNT
movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_RFI);;
ld8 r23=[r20];;
adds r23=1,r23;;
st8 [r20]=r23;;
#endif
// r18=&vpsr.i|vpsr.ic, r21==vpsr, r22=vcr.iip
mov cr.iip=r22;;
adds r20=XSI_INCOMPL_REG_OFS-XSI_PSR_IC_OFS,r18 ;;
st4 [r20]=r0 ;;
+40 -9
View File
@@ -348,12 +348,23 @@ ENTRY(alt_itlb_miss)
// ;;
//#endif
#endif
#ifdef XEN
mov r31=pr
mov r16=cr.ifa // get address that caused the TLB miss
;;
late_alt_itlb_miss:
movl r17=PAGE_KERNEL
mov r21=cr.ipsr
movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
;;
#else
mov r16=cr.ifa // get address that caused the TLB miss
movl r17=PAGE_KERNEL
mov r21=cr.ipsr
movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
mov r31=pr
;;
#endif
#ifdef CONFIG_DISABLE_VHPT
shr.u r22=r16,61 // get the region number into r21
;;
@@ -367,9 +378,15 @@ ENTRY(alt_itlb_miss)
#endif
extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
#ifdef XEN
shr.u r18=r16,55 // move address bit 59 to bit 4
;;
and r18=0x10,r18 // bit 4=address-bit(59)
#else
shr.u r18=r16,57 // move address bit 61 to bit 4
;;
andcm r18=0x10,r18 // bit 4=~address-bit(61)
#endif
cmp.ne p8,p0=r0,r23 // psr.cpl != 0?
or r19=r17,r19 // insert PTE control bits into r19
;;
@@ -393,13 +410,18 @@ ENTRY(alt_dtlb_miss)
// ;;
//#endif
#endif
#ifdef XEN
mov r31=pr
mov r16=cr.ifa // get address that caused the TLB miss
;;
late_alt_dtlb_miss:
movl r17=PAGE_KERNEL
mov r20=cr.isr
movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
mov r21=cr.ipsr
mov r31=pr
;;
#else
#endif
#ifdef CONFIG_DISABLE_VHPT
shr.u r22=r16,61 // get the region number into r21
;;
@@ -414,24 +436,33 @@ ENTRY(alt_dtlb_miss)
extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
and r22=IA64_ISR_CODE_MASK,r20 // get the isr.code field
tbit.nz p6,p7=r20,IA64_ISR_SP_BIT // is speculation bit on?
#ifdef XEN
shr.u r18=r16,55 // move address bit 59 to bit 4
and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on?
;;
and r18=0x10,r18 // bit 4=address-bit(59)
#else
shr.u r18=r16,57 // move address bit 61 to bit 4
and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on?
;;
andcm r18=0x10,r18 // bit 4=~address-bit(61)
#endif
cmp.ne p8,p0=r0,r23
(p9) cmp.eq.or.andcm p6,p7=IA64_ISR_CODE_LFETCH,r22 // check isr.code field
(p8) br.cond.spnt page_fault
#ifdef XEN
;;
// FIXME: inadequate test, this is where we test for Xen address
// note that 0xf000 (cached) and 0xd000 (uncached) addresses
// should be OK. (Though no I/O is done in Xen, EFI needs uncached
// addresses and some domain EFI calls are passed through)
tbit.nz p0,p8=r16,60
(p8) br.cond.spnt page_fault
//(p8) br.cond.spnt 0
;;
// Test for Xen address, if not handle via page_fault
// note that 0xf000 (cached) and 0xe800 (uncached) addresses
// should be OK.
extr.u r22=r16,59,5;;
cmp.eq p8,p0=0x1e,r22
(p8) br.cond.spnt 1f;;
cmp.ne p8,p0=0x1d,r22
(p8) br.cond.sptk page_fault ;;
1:
#endif
dep r21=-1,r21,IA64_PSR_ED_BIT,1
+1 -1
View File
@@ -5,7 +5,7 @@
#define SLOW_DOWN_IO do { } while (0)
+#ifdef XEN
+#define __IA64_UNCACHED_OFFSET 0xd000000000000000UL /* region 6 */
+#define __IA64_UNCACHED_OFFSET 0xe800000000000000UL
+#else
#define __IA64_UNCACHED_OFFSET 0xc000000000000000UL /* region 6 */
+#endif
+4 -4
View File
@@ -4,9 +4,9 @@
* (because the memory stack pointer MUST ALWAYS be aligned this way)
*
*/
+#ifdef CONFIG_VTI
+#include "vmx_ptrace.h"
+#else //CONFIG_VTI
+#ifdef XEN
+#include <public/arch-ia64.h>
+#else
struct pt_regs {
/* The following registers are saved by SAVE_MIN: */
unsigned long b6; /* scratch */
@@ -14,7 +14,7 @@
struct ia64_fpreg f10; /* scratch */
struct ia64_fpreg f11; /* scratch */
};
+#endif // CONFIG_VTI
+#endif
/*
* This structure contains the addition registers that need to
@@ -0,0 +1,22 @@
--- ../../linux-2.6.11/include/asm-ia64/uaccess.h 2005-06-06 10:36:23.000000000 -0600
+++ include/asm-ia64/uaccess.h 2005-06-10 18:08:06.000000000 -0600
@@ -60,6 +60,11 @@
* address TASK_SIZE is never valid. We also need to make sure that the address doesn't
* point inside the virtually mapped linear page table.
*/
+#ifdef XEN
+/* VT-i reserves bit 60 for the VMM; guest addresses have bit 60 = bit 59 */
+#define IS_VMM_ADDRESS(addr) ((((addr) >> 60) ^ ((addr) >> 59)) & 1)
+#define __access_ok(addr, size, segment) (!IS_VMM_ADDRESS((unsigned long)(addr)))
+#else
#define __access_ok(addr, size, segment) \
({ \
__chk_user_ptr(addr); \
@@ -67,6 +72,7 @@
&& ((segment).seg == KERNEL_DS.seg \
|| likely(REGION_OFFSET((unsigned long) (addr)) < RGN_MAP_LIMIT))); \
})
+#endif
#define access_ok(type, addr, size) __access_ok((addr), (size), get_fs())
static inline int
+52 -1
View File
@@ -748,10 +748,22 @@ priv_emulate(VCPU *vcpu, REGS *regs, UINT64 isr)
#define HYPERPRIVOP_ITC_D 0x5
#define HYPERPRIVOP_ITC_I 0x6
#define HYPERPRIVOP_SSM_I 0x7
#define HYPERPRIVOP_MAX 0x7
#define HYPERPRIVOP_GET_IVR 0x8
#define HYPERPRIVOP_GET_TPR 0x9
#define HYPERPRIVOP_SET_TPR 0xa
#define HYPERPRIVOP_EOI 0xb
#define HYPERPRIVOP_SET_ITM 0xc
#define HYPERPRIVOP_THASH 0xd
#define HYPERPRIVOP_PTC_GA 0xe
#define HYPERPRIVOP_ITR_D 0xf
#define HYPERPRIVOP_GET_RR 0x10
#define HYPERPRIVOP_SET_RR 0x11
#define HYPERPRIVOP_MAX 0x11
char *hyperpriv_str[HYPERPRIVOP_MAX+1] = {
0, "rfi", "rsm.dt", "ssm.dt", "cover", "itc.d", "itc.i", "ssm.i",
"=ivr", "=tpr", "tpr=", "eoi", "itm=", "thash", "ptc.ga", "itr.d",
"=rr", "rr=",
0
};
@@ -766,6 +778,7 @@ ia64_hyperprivop(unsigned long iim, REGS *regs)
struct vcpu *v = (struct domain *) current;
INST64 inst;
UINT64 val;
UINT64 itir, ifa;
// FIXME: Handle faults appropriately for these
if (!iim || iim > HYPERPRIVOP_MAX) {
@@ -797,6 +810,44 @@ ia64_hyperprivop(unsigned long iim, REGS *regs)
case HYPERPRIVOP_SSM_I:
(void)vcpu_set_psr_i(v);
return 1;
case HYPERPRIVOP_GET_IVR:
(void)vcpu_get_ivr(v,&val);
regs->r8 = val;
return 1;
case HYPERPRIVOP_GET_TPR:
(void)vcpu_get_tpr(v,&val);
regs->r8 = val;
return 1;
case HYPERPRIVOP_SET_TPR:
(void)vcpu_set_tpr(v,regs->r8);
return 1;
case HYPERPRIVOP_EOI:
(void)vcpu_set_eoi(v,0L);
return 1;
case HYPERPRIVOP_SET_ITM:
(void)vcpu_set_itm(v,regs->r8);
return 1;
case HYPERPRIVOP_THASH:
(void)vcpu_thash(v,regs->r8,&val);
regs->r8 = val;
return 1;
case HYPERPRIVOP_PTC_GA:
// FIXME: this doesn't seem to work yet, turned off
//(void)vcpu_ptc_ga(v,regs->r8,regs->r9);
//return 1;
break;
case HYPERPRIVOP_ITR_D:
(void)vcpu_get_itir(v,&itir);
(void)vcpu_get_ifa(v,&ifa);
(void)vcpu_itr_d(v,regs->r8,regs->r9,itir,ifa);
return 1;
case HYPERPRIVOP_GET_RR:
(void)vcpu_get_rr(v,regs->r8,&val);
regs->r8 = val;
return 1;
case HYPERPRIVOP_SET_RR:
(void)vcpu_set_rr(v,regs->r8,regs->r9);
return 1;
}
return 0;
}
+18 -32
View File
@@ -313,45 +313,31 @@ void xen_handle_domain_access(unsigned long address, unsigned long isr, struct p
}
if (address < 0x4000) printf("WARNING: page_fault @%p, iip=%p\n",address,iip);
if (trp = match_tr(current,address)) {
// FIXME address had better be pre-validated on insert
pteval = translate_domain_pte(trp->page_flags,address,trp->itir);
vcpu_itc_no_srlz(current,6,address,pteval,-1UL,(trp->itir>>2)&0x3f);
return;
}
// if we are fortunate enough to have it in the 1-entry TLB...
if (pteval = match_dtlb(ed,address,&ps,NULL)) {
vcpu_itc_no_srlz(ed,6,address,pteval,-1UL,ps);
return;
}
// look in the TRs
fault = vcpu_tpa(ed,address,&mpaddr);
if (fault != IA64_NO_FAULT) {
static int uacnt = 0;
// can't translate it, just fail (poor man's exception)
// which results in retrying execution
//printk("*** xen_handle_domain_access: poor man's exception cnt=%i iip=%p, addr=%p...\n",uacnt++,iip,address);
if (ia64_done_with_exception(regs)) {
if (ia64_done_with_exception(regs)) {
//if (!(uacnt++ & 0x3ff)) printk("*** xen_handle_domain_access: successfully handled cnt=%d iip=%p, addr=%p...\n",uacnt,iip,address);
return;
}
else {
// should never happen. If it does, region 0 addr may
// indicate a bad xen pointer
printk("*** xen_handle_domain_access: exception table"
" lookup failed, iip=%p, addr=%p, spinning...\n",
iip,address);
panic_domain(regs,"*** xen_handle_domain_access: exception table"
" lookup failed, iip=%p, addr=%p, spinning...\n",
iip,address);
}
}
if (d == dom0) {
if (mpaddr < dom0_start || mpaddr >= dom0_start + dom0_size) {
printk("xen_handle_domain_access: vcpu_tpa returned out-of-bounds dom0 mpaddr %p! continuing...\n",mpaddr);
tdpfoo();
}
else {
// should never happen. If it does, region 0 addr may
// indicate a bad xen pointer
printk("*** xen_handle_domain_access: exception table"
" lookup failed, iip=%p, addr=%p, spinning...\n",
iip,address);
panic_domain(regs,"*** xen_handle_domain_access: exception table"
" lookup failed, iip=%p, addr=%p, spinning...\n",
iip,address);
}
//printk("*** xen_handle_domain_access: tpa resolved miss @%p...\n",address);
pteval = lookup_domain_mpa(d,mpaddr);
// would be nice to have a counter here
//printf("Handling privop data TLB miss\n");
// FIXME, must be inlined or potential for nested fault here!
vcpu_itc_no_srlz(ed,2,address,pteval,-1UL,PAGE_SHIFT);
}
void ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs, unsigned long itir)
@@ -441,7 +427,7 @@ panic_domain(0,"ia64_do_page_fault: @%p???, iip=%p, b0=%p, itc=%p (spinning...)\
if (pteval & _PAGE_P)
{
pteval = translate_domain_pte(pteval,address,itir);
vcpu_itc_no_srlz(current,is_data?2:1,address,pteval,-1UL,(itir>>2)&0x3f);
vcpu_itc_no_srlz(current,is_data?6:1,address,pteval,-1UL,(itir>>2)&0x3f);
return;
}
else vector = is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR;
@@ -768,7 +754,7 @@ if (!running_on_sim) { printf("SSC_OPEN, not implemented on hardware. (ignoring
vcpu_set_gr(current,8,-1L);
break;
default:
printf("ia64_handle_break: bad ssc code %lx, iip=%p\n",ssc,regs->cr_iip);
printf("ia64_handle_break: bad ssc code %lx, iip=%p, b0=%p\n",ssc,regs->cr_iip,regs->b0);
break;
}
vcpu_increment_iip(current);
+10
View File
@@ -274,6 +274,7 @@ int set_one_rr(unsigned long rr, unsigned long val)
return 0;
}
#ifdef CONFIG_VTI
memrrv.rrval = rrv.rrval;
if (rreg == 7) {
newrrv.rid = newrid;
@@ -290,6 +291,15 @@ int set_one_rr(unsigned long rr, unsigned long val)
if (rreg == 0) v->arch.metaphysical_saved_rr0 = newrrv.rrval;
set_rr(rr,newrrv.rrval);
}
#else
memrrv.rrval = rrv.rrval;
newrrv.rid = newrid;
newrrv.ve = 1; // VHPT now enabled for region 7!!
newrrv.ps = PAGE_SHIFT;
if (rreg == 0) v->arch.metaphysical_saved_rr0 = newrrv.rrval;
if (rreg == 7) ia64_new_rr7(vmMangleRID(newrrv.rrval),v->vcpu_info);
else set_rr(rr,newrrv.rrval);
#endif
return 1;
}
+1 -1
View File
@@ -259,7 +259,7 @@ softlink include/asm-ia64/string.h include/asm-ia64/string.h
softlink include/asm-ia64/thread_info.h include/asm-ia64/thread_info.h
softlink include/asm-ia64/timex.h include/asm-ia64/timex.h
softlink include/asm-ia64/topology.h include/asm-ia64/topology.h
softlink include/asm-ia64/uaccess.h include/asm-ia64/uaccess.h
cp_patch include/asm-ia64/uaccess.h include/asm-ia64/uaccess.h uaccess.h
softlink include/asm-ia64/unaligned.h include/asm-ia64/unaligned.h
softlink include/asm-ia64/unistd.h include/asm-ia64/unistd.h
softlink include/asm-ia64/unwind.h include/asm-ia64/unwind.h
+14 -8
View File
@@ -43,8 +43,9 @@ typedef union {
#ifdef PRIVOP_ADDR_COUNT
struct privop_addr_count privop_addr_counter[PRIVOP_COUNT_NINSTS] = {
{ "rsm", { 0 }, { 0 }, 0 },
{ "ssm", { 0 }, { 0 }, 0 }
{ "=ifa", { 0 }, { 0 }, 0 },
{ "thash", { 0 }, { 0 }, 0 },
0
};
extern void privop_count_addr(unsigned long addr, int inst);
#define PRIVOP_COUNT_ADDR(regs,inst) privop_count_addr(regs->cr_iip,inst)
@@ -135,7 +136,7 @@ IA64FAULT vcpu_reset_psr_sm(VCPU *vcpu, UINT64 imm24)
struct ia64_psr psr, imm, *ipsr;
REGS *regs = vcpu_regs(vcpu);
PRIVOP_COUNT_ADDR(regs,_RSM);
//PRIVOP_COUNT_ADDR(regs,_RSM);
// TODO: All of these bits need to be virtualized
// TODO: Only allowed for current vcpu
__asm__ __volatile ("mov %0=psr;;" : "=r"(psr) :: "memory");
@@ -183,7 +184,7 @@ IA64FAULT vcpu_set_psr_sm(VCPU *vcpu, UINT64 imm24)
REGS *regs = vcpu_regs(vcpu);
UINT64 mask, enabling_interrupts = 0;
PRIVOP_COUNT_ADDR(regs,_SSM);
//PRIVOP_COUNT_ADDR(regs,_SSM);
// TODO: All of these bits need to be virtualized
__asm__ __volatile ("mov %0=psr;;" : "=r"(psr) :: "memory");
imm = *(struct ia64_psr *)&imm24;
@@ -369,6 +370,8 @@ IA64FAULT vcpu_get_iip(VCPU *vcpu, UINT64 *pval)
IA64FAULT vcpu_get_ifa(VCPU *vcpu, UINT64 *pval)
{
UINT64 val = PSCB(vcpu,ifa);
REGS *regs = vcpu_regs(vcpu);
PRIVOP_COUNT_ADDR(regs,_GET_IFA);
*pval = val;
return (IA64_NO_FAULT);
}
@@ -422,6 +425,8 @@ IA64FAULT vcpu_get_iha(VCPU *vcpu, UINT64 *pval)
{
//return vcpu_thash(vcpu,PSCB(vcpu,ifa),pval);
UINT64 val = PSCB(vcpu,iha);
REGS *regs = vcpu_regs(vcpu);
PRIVOP_COUNT_ADDR(regs,_THASH);
*pval = val;
return (IA64_NO_FAULT);
}
@@ -539,7 +544,7 @@ void vcpu_pend_interrupt(VCPU *vcpu, UINT64 vector)
} else
#endif // CONFIG_VTI
{
if (!test_bit(vector,PSCB(vcpu,delivery_mask))) return;
/* if (!test_bit(vector,PSCB(vcpu,delivery_mask))) return; */
if (test_bit(vector,PSCBX(vcpu,irr))) {
//printf("vcpu_pend_interrupt: overrun\n");
}
@@ -569,10 +574,10 @@ UINT64 vcpu_check_pending_interrupts(VCPU *vcpu)
UINT64 *p, *q, *r, bits, bitnum, mask, i, vector;
p = &PSCBX(vcpu,irr[3]);
q = &PSCB(vcpu,delivery_mask[3]);
/* q = &PSCB(vcpu,delivery_mask[3]); */
r = &PSCBX(vcpu,insvc[3]);
for (i = 3; ; p--, q--, r--, i--) {
bits = *p & *q;
bits = *p /* & *q */;
if (bits) break; // got a potential interrupt
if (*r) {
// nothing in this word which is pending+inservice
@@ -1589,7 +1594,8 @@ void vcpu_itc_no_srlz(VCPU *vcpu, UINT64 IorD, UINT64 vaddr, UINT64 pte, UINT64
// addresses never get flushed. More work needed if this
// ever happens.
//printf("vhpt_insert(%p,%p,%p)\n",vaddr,pte,1L<<logps);
vhpt_insert(vaddr,pte,logps<<2);
if (logps > PAGE_SHIFT) vhpt_multiple_insert(vaddr,pte,logps);
else vhpt_insert(vaddr,pte,logps<<2);
}
// even if domain pagesize is larger than PAGE_SIZE, just put
// PAGE_SIZE mapping in the vhpt for now, else purging is complicated
+31
View File
@@ -87,6 +87,37 @@ void vhpt_map(void)
ia64_srlz_i();
}
void vhpt_multiple_insert(unsigned long vaddr, unsigned long pte, unsigned long logps)
{
unsigned long mask = (1L << logps) - 1;
int i;
if (logps-PAGE_SHIFT > 10) {
// if this happens, we may want to revisit this algorithm
printf("vhpt_multiple_insert:logps-PAGE_SHIFT>10,spinning..\n");
while(1);
}
if (logps-PAGE_SHIFT > 2) {
// FIXME: Should add counter here to see how often this
// happens (e.g. for 16MB pages!) and determine if it
// is a performance problem. On a quick look, it takes
// about 39000 instrs for a 16MB page and it seems to occur
// only a few times/second, so OK for now.
// An alternate solution would be to just insert the one
// 16KB in the vhpt (but with the full mapping)?
//printf("vhpt_multiple_insert: logps-PAGE_SHIFT==%d,"
//"va=%p, pa=%p, pa-masked=%p\n",
//logps-PAGE_SHIFT,vaddr,pte&_PFN_MASK,
//(pte&_PFN_MASK)&~mask);
}
vaddr &= ~mask;
pte = ((pte & _PFN_MASK) & ~mask) | (pte & ~_PFN_MASK);
for (i = 1L << (logps-PAGE_SHIFT); i > 0; i--) {
vhpt_insert(vaddr,pte,logps<<2);
vaddr += PAGE_SIZE;
}
}
void vhpt_init(void)
{
unsigned long vhpt_total_size, vhpt_alignment, vhpt_imva;
+34 -42
View File
@@ -454,12 +454,13 @@ IA64FAULT vmx_vcpu_itc_i(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
data.page_flags=pte & ~PAGE_FLAGS_RV_MASK;
data.itir=itir;
data.vadr=PAGEALIGN(ifa,data.ps);
data.section=THASH_TLB_TC;
data.tc = 1;
data.cl=ISIDE_TLB;
vmx_vcpu_get_rr(vcpu, ifa, &vrr);
data.rid = vrr.rid;
sections.v = THASH_SECTION_TR;
sections.tr = 1;
sections.tc = 0;
ovl = thash_find_overlap(hcb, &data, sections);
while (ovl) {
@@ -467,9 +468,7 @@ IA64FAULT vmx_vcpu_itc_i(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
panic("Tlb conflict!!");
return;
}
sections.v = THASH_SECTION_TC;
thash_purge_entries(hcb, &data, sections);
thash_insert(hcb, &data, ifa);
thash_purge_and_insert(hcb, &data);
return IA64_NO_FAULT;
}
@@ -488,11 +487,12 @@ IA64FAULT vmx_vcpu_itc_d(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
data.page_flags=pte & ~PAGE_FLAGS_RV_MASK;
data.itir=itir;
data.vadr=PAGEALIGN(ifa,data.ps);
data.section=THASH_TLB_TC;
data.tc = 1;
data.cl=DSIDE_TLB;
vmx_vcpu_get_rr(vcpu, ifa, &vrr);
data.rid = vrr.rid;
sections.v = THASH_SECTION_TR;
sections.tr = 1;
sections.tc = 0;
ovl = thash_find_overlap(hcb, &data, sections);
if (ovl) {
@@ -500,42 +500,27 @@ IA64FAULT vmx_vcpu_itc_d(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
panic("Tlb conflict!!");
return;
}
sections.v = THASH_SECTION_TC;
thash_purge_entries(hcb, &data, sections);
thash_insert(hcb, &data, ifa);
thash_purge_and_insert(hcb, &data);
return IA64_NO_FAULT;
}
IA64FAULT insert_foreignmap(VCPU *vcpu, UINT64 pte, UINT64 ps, UINT64 va)
/*
* Return TRUE/FALSE for success of lock operation
*/
int vmx_lock_guest_dtc (VCPU *vcpu, UINT64 va, int lock)
{
thash_data_t data, *ovl;
thash_cb_t *hcb;
search_section_t sections;
rr_t vrr;
rr_t vrr;
u64 preferred_size;
hcb = vmx_vcpu_get_vtlb(vcpu);
data.page_flags=pte & ~PAGE_FLAGS_RV_MASK;
data.itir=0;
data.ps = ps;
data.vadr=PAGEALIGN(va,ps);
data.section=THASH_TLB_FM;
data.cl=DSIDE_TLB;
vmx_vcpu_get_rr(vcpu, va, &vrr);
data.rid = vrr.rid;
sections.v = THASH_SECTION_TR|THASH_SECTION_TC|THASH_SECTION_FM;
ovl = thash_find_overlap(hcb, &data, sections);
if (ovl) {
// generate MCA.
panic("Foreignmap Tlb conflict!!");
return;
}
thash_insert(hcb, &data, va);
return IA64_NO_FAULT;
hcb = vmx_vcpu_get_vtlb(vcpu);
va = PAGEALIGN(va,vrr.ps);
preferred_size = PSIZE(vrr.ps);
return thash_lock_tc(hcb, va, preferred_size, vrr.rid, DSIDE_TLB, lock);
}
IA64FAULT vmx_vcpu_itr_i(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa, UINT64 idx)
{
@@ -548,11 +533,12 @@ IA64FAULT vmx_vcpu_itr_i(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa, UINT64
data.page_flags=pte & ~PAGE_FLAGS_RV_MASK;
data.itir=itir;
data.vadr=PAGEALIGN(ifa,data.ps);
data.section=THASH_TLB_TR;
data.tc = 0;
data.cl=ISIDE_TLB;
vmx_vcpu_get_rr(vcpu, ifa, &vrr);
data.rid = vrr.rid;
sections.v = THASH_SECTION_TR;
sections.tr = 1;
sections.tc = 0;
ovl = thash_find_overlap(hcb, &data, sections);
if (ovl) {
@@ -560,7 +546,8 @@ IA64FAULT vmx_vcpu_itr_i(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa, UINT64
panic("Tlb conflict!!");
return;
}
sections.v=THASH_SECTION_TC;
sections.tr = 0;
sections.tc = 1;
thash_purge_entries(hcb, &data, sections);
thash_tr_insert(hcb, &data, ifa, idx);
return IA64_NO_FAULT;
@@ -579,11 +566,12 @@ IA64FAULT vmx_vcpu_itr_d(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa, UINT64
data.page_flags=pte & ~PAGE_FLAGS_RV_MASK;
data.itir=itir;
data.vadr=PAGEALIGN(ifa,data.ps);
data.section=THASH_TLB_TR;
data.tc = 0;
data.cl=DSIDE_TLB;
vmx_vcpu_get_rr(vcpu, ifa, &vrr);
data.rid = vrr.rid;
sections.v = THASH_SECTION_TR;
sections.tr = 1;
sections.tc = 0;
ovl = thash_find_overlap(hcb, &data, sections);
while (ovl) {
@@ -591,7 +579,8 @@ IA64FAULT vmx_vcpu_itr_d(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa, UINT64
panic("Tlb conflict!!");
return;
}
sections.v=THASH_SECTION_TC;
sections.tr = 0;
sections.tc = 1;
thash_purge_entries(hcb, &data, sections);
thash_tr_insert(hcb, &data, ifa, idx);
return IA64_NO_FAULT;
@@ -607,7 +596,8 @@ IA64FAULT vmx_vcpu_ptr_d(VCPU *vcpu,UINT64 vadr,UINT64 ps)
hcb = vmx_vcpu_get_vtlb(vcpu);
rr=vmx_vcpu_rr(vcpu,vadr);
sections.v = THASH_SECTION_TR | THASH_SECTION_TC;
sections.tr = 1;
sections.tc = 1;
thash_purge_entries_ex(hcb,rr.rid,vadr,ps,sections,DSIDE_TLB);
return IA64_NO_FAULT;
}
@@ -619,7 +609,8 @@ IA64FAULT vmx_vcpu_ptr_i(VCPU *vcpu,UINT64 vadr,UINT64 ps)
search_section_t sections;
hcb = vmx_vcpu_get_vtlb(vcpu);
rr=vmx_vcpu_rr(vcpu,vadr);
sections.v = THASH_SECTION_TR | THASH_SECTION_TC;
sections.tr = 1;
sections.tc = 1;
thash_purge_entries_ex(hcb,rr.rid,vadr,ps,sections,ISIDE_TLB);
return IA64_NO_FAULT;
}
@@ -632,7 +623,8 @@ IA64FAULT vmx_vcpu_ptc_l(VCPU *vcpu, UINT64 vadr, UINT64 ps)
thash_data_t data, *ovl;
hcb = vmx_vcpu_get_vtlb(vcpu);
vrr=vmx_vcpu_rr(vcpu,vadr);
sections.v = THASH_SECTION_TC;
sections.tr = 0;
sections.tc = 1;
vadr = PAGEALIGN(vadr, ps);
thash_purge_entries_ex(hcb,vrr.rid,vadr,ps,sections,DSIDE_TLB);
+76 -8
View File
@@ -180,7 +180,7 @@ ENTRY(vmx_dtlb_miss)
mov r29=cr.ipsr;
;;
tbit.z p6,p7=r29,IA64_PSR_VM_BIT;
(p6)br.sptk vmx_fault_1
(p6)br.sptk vmx_fault_2
mov r16 = cr.ifa
;;
thash r17 = r16
@@ -249,9 +249,9 @@ ENTRY(vmx_alt_itlb_miss)
movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
;;
and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
shr.u r18=r16,57 // move address bit 61 to bit 4
shr.u r18=r16,55 // move address bit 59 to bit 4
;;
andcm r18=0x10,r18 // bit 4=~address-bit(61)
and r18=0x10,r18 // bit 4=address-bit(61)
or r19=r17,r19 // insert PTE control bits into r19
;;
or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6
@@ -280,11 +280,11 @@ ENTRY(vmx_alt_dtlb_miss)
;;
and r22=IA64_ISR_CODE_MASK,r20 // get the isr.code field
tbit.nz p6,p7=r20,IA64_ISR_SP_BIT // is speculation bit on?
shr.u r18=r16,57 // move address bit 61 to bit 4
shr.u r18=r16,55 // move address bit 59 to bit 4
and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on?
;;
andcm r18=0x10,r18 // bit 4=~address-bit(61)
and r18=0x10,r18 // bit 4=address-bit(61)
(p9) cmp.eq.or.andcm p6,p7=IA64_ISR_CODE_LFETCH,r22 // check isr.code field
dep r24=-1,r24,IA64_PSR_ED_BIT,1
or r19=r19,r17 // insert PTE control bits into r19
@@ -346,7 +346,12 @@ END(vmx_daccess_bit)
ENTRY(vmx_break_fault)
mov r31=pr
mov r19=11
br.sptk.many vmx_dispatch_break_fault
mov r30=cr.iim
mov r29=0x1100
;;
cmp4.eq p6,p7=r29,r30
(p6) br.dptk.few vmx_hypercall_dispatch
(p7) br.sptk.many vmx_dispatch_break_fault
END(vmx_break_fault)
.org vmx_ia64_ivt+0x3000
@@ -929,10 +934,9 @@ END(vmx_dispatch_tlb_miss)
ENTRY(vmx_dispatch_break_fault)
cmp.ne pEml,pNonEml=r0,r0 /* force pNonEml =1, don't save r4 ~ r7 */
;;
VMX_SAVE_MIN_WITH_COVER_R19
;;
;;
alloc r14=ar.pfs,0,0,4,0 // now it's safe (must be first in insn group!)
mov out0=cr.ifa
adds out1=16,sp
@@ -951,9 +955,37 @@ ENTRY(vmx_dispatch_break_fault)
;;
mov rp=r14
br.call.sptk.many b6=vmx_ia64_handle_break
;;
END(vmx_dispatch_break_fault)
ENTRY(vmx_hypercall_dispatch)
VMX_SAVE_MIN_WITH_COVER
ssm psr.ic
;;
srlz.i // guarantee that interruption collection is on
;;
ssm psr.i // restore psr.i
adds r3=16,r2 // set up second base pointer
;;
VMX_SAVE_REST
;;
movl r14=ia64_leave_hypervisor
movl r2=hyper_call_table
;;
mov rp=r14
shladd r2=r15,3,r2
;;
ld8 r2=[r2]
;;
mov b6=r2
;;
br.call.sptk.many b6=b6
;;
END(vmx_hypercall_dispatch)
ENTRY(vmx_dispatch_interrupt)
cmp.ne pEml,pNonEml=r0,r0 /* force pNonEml =1, don't save r4 ~ r7 */
;;
@@ -976,3 +1008,39 @@ ENTRY(vmx_dispatch_interrupt)
mov rp=r14
br.call.sptk.many b6=vmx_ia64_handle_irq
END(vmx_dispatch_interrupt)
.rodata
.align 8
.globl hyper_call_table
hyper_call_table:
data8 hyper_not_support //hyper_set_trap_table /* 0 */
data8 hyper_mmu_update
data8 hyper_not_support //hyper_set_gdt
data8 hyper_not_support //hyper_stack_switch
data8 hyper_not_support //hyper_set_callbacks
data8 hyper_not_support //hyper_fpu_taskswitch /* 5 */
data8 hyper_sched_op
data8 hyper_dom0_op
data8 hyper_not_support //hyper_set_debugreg
data8 hyper_not_support //hyper_get_debugreg
data8 hyper_not_support //hyper_update_descriptor /* 10 */
data8 hyper_not_support //hyper_set_fast_trap
data8 hyper_dom_mem_op
data8 hyper_not_support //hyper_multicall
data8 hyper_not_support //hyper_update_va_mapping
data8 hyper_not_support //hyper_set_timer_op /* 15 */
data8 hyper_event_channel_op
data8 hyper_xen_version
data8 hyper_not_support //hyper_console_io
data8 hyper_not_support //hyper_physdev_op
data8 hyper_not_support //hyper_grant_table_op /* 20 */
data8 hyper_not_support //hyper_vm_assist
data8 hyper_not_support //hyper_update_va_mapping_otherdomain
data8 hyper_not_support //hyper_switch_vm86
data8 hyper_not_support //hyper_boot_vcpu
data8 hyper_not_support //hyper_ni_hypercall /* 25 */
data8 hyper_not_support //hyper_mmuext_op
data8 hyper_lock_page
data8 hyper_set_shared_page
+4 -4
View File
@@ -282,11 +282,9 @@
;; \
.mem.offset 0,0; st8.spill [r4]=r20,16; \
.mem.offset 8,0; st8.spill [r5]=r21,16; \
mov r18=b6; \
;; \
.mem.offset 0,0; st8.spill [r4]=r22,16; \
.mem.offset 8,0; st8.spill [r5]=r23,16; \
mov r19=b7; \
;; \
.mem.offset 0,0; st8.spill [r4]=r24,16; \
.mem.offset 8,0; st8.spill [r5]=r25,16; \
@@ -296,9 +294,11 @@
;; \
.mem.offset 0,0; st8.spill [r4]=r28,16; \
.mem.offset 8,0; st8.spill [r5]=r29,16; \
mov r26=b6; \
;; \
.mem.offset 0,0; st8.spill [r4]=r30,16; \
.mem.offset 8,0; st8.spill [r5]=r31,16; \
mov r27=b7; \
;; \
mov r30=ar.unat; \
;; \
@@ -317,8 +317,8 @@
adds r2=PT(B6)-PT(F10),r2; \
adds r3=PT(B7)-PT(F11),r3; \
;; \
st8 [r2]=r18,16; /* b6 */ \
st8 [r3]=r19,16; /* b7 */ \
st8 [r2]=r26,16; /* b6 */ \
st8 [r3]=r27,16; /* b7 */ \
;; \
st8 [r2]=r9; /* ar.csd */ \
st8 [r3]=r10; /* ar.ssd */ \
-1
View File
@@ -116,7 +116,6 @@ vmx_ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long is
case FW_HYPERCALL_EFI_GET_TIME:
{
unsigned long *tv, *tc;
fooefi();
vmx_vcpu_get_gr(v, 32, &tv);
vmx_vcpu_get_gr(v, 33, &tc);
printf("efi_get_time(%p,%p) called...",tv,tc);
+82 -14
View File
@@ -252,7 +252,7 @@ static thash_data_t *_vtlb_next_overlap_in_chain(thash_cb_t *hcb)
/* Find overlap TLB entry */
for (cch=priv->cur_cch; cch; cch = cch->next) {
if ( ((1UL<<cch->section) & priv->s_sect.v) &&
if ( ( cch->tc ? priv->s_sect.tc : priv->s_sect.tr ) &&
__is_tlb_overlap(hcb, cch, priv->rid, priv->cl,
priv->_curva, priv->_eva) ) {
return cch;
@@ -322,7 +322,7 @@ int __tlb_to_vhpt(thash_cb_t *hcb,
void thash_tr_insert(thash_cb_t *hcb, thash_data_t *entry, u64 va, int idx)
{
if ( hcb->ht != THASH_TLB || entry->section != THASH_TLB_TR ) {
if ( hcb->ht != THASH_TLB || entry->tc ) {
panic("wrong parameter\n");
}
entry->vadr = PAGEALIGN(entry->vadr,entry->ps);
@@ -356,7 +356,7 @@ thash_data_t *__alloc_chain(thash_cb_t *hcb,thash_data_t *entry)
* 3: The caller need to make sure the new entry will not overlap
* with any existed entry.
*/
static void vtlb_insert(thash_cb_t *hcb, thash_data_t *entry, u64 va)
void vtlb_insert(thash_cb_t *hcb, thash_data_t *entry, u64 va)
{
thash_data_t *hash_table, *cch;
rr_t vrr;
@@ -411,7 +411,7 @@ void thash_insert(thash_cb_t *hcb, thash_data_t *entry, u64 va)
rr_t vrr;
vrr = (hcb->get_rr_fn)(hcb->vcpu,entry->vadr);
if ( entry->ps != vrr.ps && entry->section==THASH_TLB_TC) {
if ( entry->ps != vrr.ps && entry->tc ) {
panic("Not support for multiple page size now\n");
}
entry->vadr = PAGEALIGN(entry->vadr,entry->ps);
@@ -450,7 +450,7 @@ static void rem_vtlb(thash_cb_t *hcb, thash_data_t *entry)
thash_internal_t *priv = &hcb->priv;
int idx;
if ( entry->section == THASH_TLB_TR ) {
if ( !entry->tc ) {
return rem_tr(hcb, entry->cl, entry->tr_idx);
}
rem_thash(hcb, entry);
@@ -525,19 +525,19 @@ thash_data_t *thash_find_overlap(thash_cb_t *hcb,
thash_data_t *in, search_section_t s_sect)
{
return (hcb->find_overlap)(hcb, in->vadr,
in->ps, in->rid, in->cl, s_sect);
PSIZE(in->ps), in->rid, in->cl, s_sect);
}
static thash_data_t *vtlb_find_overlap(thash_cb_t *hcb,
u64 va, u64 ps, int rid, char cl, search_section_t s_sect)
u64 va, u64 size, int rid, char cl, search_section_t s_sect)
{
thash_data_t *hash_table;
thash_internal_t *priv = &hcb->priv;
u64 tag;
rr_t vrr;
priv->_curva = PAGEALIGN(va,ps);
priv->_eva = priv->_curva + PSIZE(ps);
priv->_curva = va & ~(size-1);
priv->_eva = priv->_curva + size;
priv->rid = rid;
vrr = (hcb->get_rr_fn)(hcb->vcpu,va);
priv->ps = vrr.ps;
@@ -553,15 +553,15 @@ static thash_data_t *vtlb_find_overlap(thash_cb_t *hcb,
}
static thash_data_t *vhpt_find_overlap(thash_cb_t *hcb,
u64 va, u64 ps, int rid, char cl, search_section_t s_sect)
u64 va, u64 size, int rid, char cl, search_section_t s_sect)
{
thash_data_t *hash_table;
thash_internal_t *priv = &hcb->priv;
u64 tag;
rr_t vrr;
priv->_curva = PAGEALIGN(va,ps);
priv->_eva = priv->_curva + PSIZE(ps);
priv->_curva = va & ~(size-1);
priv->_eva = priv->_curva + size;
priv->rid = rid;
vrr = (hcb->get_rr_fn)(hcb->vcpu,va);
priv->ps = vrr.ps;
@@ -691,13 +691,46 @@ void thash_purge_entries_ex(thash_cb_t *hcb,
{
thash_data_t *ovl;
ovl = (hcb->find_overlap)(hcb, va, ps, rid, cl, p_sect);
ovl = (hcb->find_overlap)(hcb, va, PSIZE(ps), rid, cl, p_sect);
while ( ovl != NULL ) {
(hcb->rem_hash)(hcb, ovl);
ovl = (hcb->next_overlap)(hcb);
};
}
/*
* Purge overlap TCs and then insert the new entry to emulate itc ops.
* Notes: Only TC entry can purge and insert.
*/
void thash_purge_and_insert(thash_cb_t *hcb, thash_data_t *in)
{
thash_data_t *ovl;
search_section_t sections;
#ifdef XEN_DEBUGGER
vrr = (hcb->get_rr_fn)(hcb->vcpu,in->vadr);
if ( in->ps != vrr.ps || hcb->ht != THASH_TLB || !in->tc ) {
panic ("Oops, wrong call for purge_and_insert\n");
return;
}
#endif
in->vadr = PAGEALIGN(in->vadr,in->ps);
in->ppn = PAGEALIGN(in->ppn, in->ps-12);
sections.tr = 0;
sections.tc = 1;
ovl = (hcb->find_overlap)(hcb, in->vadr, PSIZE(in->ps),
in->rid, in->cl, sections);
if(ovl)
(hcb->rem_hash)(hcb, ovl);
#ifdef XEN_DEBUGGER
ovl = (hcb->next_overlap)(hcb);
if ( ovl ) {
panic ("Oops, 2+ overlaps for purge_and_insert\n");
return;
}
#endif
(hcb->ins_hash)(hcb, in, in->vadr);
}
/*
* Purge all TCs or VHPT entries including those in Hash table.
@@ -766,6 +799,42 @@ thash_data_t *vtlb_lookup_ex(thash_cb_t *hcb,
return NULL;
}
/*
* Lock/Unlock TC if found.
* NOTES: Only the page in prefered size can be handled.
* return:
* 1: failure
* 0: success
*/
int thash_lock_tc(thash_cb_t *hcb, u64 va, u64 size, int rid, char cl, int lock)
{
thash_data_t *ovl;
search_section_t sections;
sections.tr = 1;
sections.tc = 1;
ovl = (hcb->find_overlap)(hcb, va, size, rid, cl, sections);
if ( ovl ) {
if ( !ovl->tc ) {
// panic("Oops, TR for lock\n");
return 0;
}
else if ( lock ) {
if ( ovl->locked ) {
DPRINTK("Oops, already locked entry\n");
}
ovl->locked = 1;
}
else if ( !lock ) {
if ( !ovl->locked ) {
DPRINTK("Oops, already unlocked entry\n");
}
ovl->locked = 0;
}
return 0;
}
return 1;
}
/*
* Notifier when TLB is deleted from hash table and its collision chain.
@@ -824,7 +893,6 @@ void thash_init(thash_cb_t *hcb, u64 sz)
}
}
#ifdef VTLB_DEBUG
static u64 cch_length_statistics[MAX_CCH_LENGTH+1];
u64 sanity_check=0;
+1 -1
View File
@@ -52,7 +52,7 @@ paging_init (void)
panic("Not enough memory to bootstrap Xen.\n");
printk("machine to physical table: 0x%lx\n", (u64)mpt_table);
memset(mpt_table, 0x55, mpt_table_size);
memset(mpt_table, INVALID_M2P_ENTRY, mpt_table_size);
/* Any more setup here? On VMX enabled platform,
* there's no need to keep guest linear pg table,
+1 -7
View File
@@ -63,13 +63,7 @@ void sync_lazy_execstate_mask(cpumask_t mask) {}
void sync_lazy_execstate_all(void) {}
int grant_table_create(struct domain *d) { return 0; }
void grant_table_destroy(struct domain *d)
{
printf("grant_table_destroy: domain_destruct not tested!!!\n");
printf("grant_table_destroy: ensure atomic_* calls work in domain_destruct!!\n");
dummy();
return;
}
void grant_table_destroy(struct domain *d) { return; }
struct pt_regs *guest_cpu_user_regs(void) { return ia64_task_regs(current); }
+18 -11
View File
@@ -193,23 +193,30 @@ static void __init init_amd(struct cpuinfo_x86 *c)
}
display_cacheinfo(c);
detect_ht(c);
#ifdef CONFIG_X86_HT
/* AMD dual core looks like HT but isn't really. Hide it from the
scheduler. This works around problems with the domain scheduler.
Also probably gives slightly better scheduling and disables
SMT nice which is harmful on dual core.
TBD tune the domain scheduler for dual core. */
if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
smp_num_siblings = 1;
#endif
if (cpuid_eax(0x80000000) >= 0x80000008) {
c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
if (c->x86_num_cores & (c->x86_num_cores - 1))
c->x86_num_cores = 1;
}
#ifdef CONFIG_X86_HT
/*
* On a AMD dual core setup the lower bits of the APIC id
* distingush the cores. Assumes number of cores is a power
* of two.
*/
if (c->x86_num_cores > 1) {
int cpu = smp_processor_id();
unsigned bits = 0;
while ((1 << bits) < c->x86_num_cores)
bits++;
cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1);
phys_proc_id[cpu] >>= bits;
printk(KERN_INFO "CPU %d(%d) -> Core %d\n",
cpu, c->x86_num_cores, cpu_core_id[cpu]);
}
#endif
}
static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
+27 -22
View File
@@ -186,7 +186,7 @@ static inline int flag_is_changeable_p(unsigned long flag)
/* Probe for the CPUID instruction */
int __init have_cpuid_p(void)
static int __init have_cpuid_p(void)
{
return flag_is_changeable_p(X86_EFLAGS_ID);
}
@@ -194,7 +194,7 @@ int __init have_cpuid_p(void)
/* Do minimum CPU detection early.
Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment.
The others are not touched to avoid unwanted side effects. */
void __init early_cpu_detect(void)
static void __init early_cpu_detect(void)
{
struct cpuinfo_x86 *c = &boot_cpu_data;
@@ -228,6 +228,10 @@ void __init early_cpu_detect(void)
}
early_intel_workaround(c);
#ifdef CONFIG_X86_HT
phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
#endif
}
void __init generic_identify(struct cpuinfo_x86 * c)
@@ -416,25 +420,15 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
mcheck_init(c);
#endif
}
/*
* Perform early boot up checks for a valid TSC. See arch/i386/kernel/time.c
*/
void __init dodgy_tsc(void)
{
if (( boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX ) ||
( boot_cpu_data.x86_vendor == X86_VENDOR_NSC ))
cpu_devs[X86_VENDOR_CYRIX]->c_init(&boot_cpu_data);
}
#ifdef CONFIG_X86_HT
void __init detect_ht(struct cpuinfo_x86 *c)
{
u32 eax, ebx, ecx, edx;
int index_lsb, index_msb, tmp;
int index_msb, tmp;
int cpu = smp_processor_id();
if (!cpu_has(c, X86_FEATURE_HT))
if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
return;
cpuid(1, &eax, &ebx, &ecx, &edx);
@@ -443,7 +437,6 @@ void __init detect_ht(struct cpuinfo_x86 *c)
if (smp_num_siblings == 1) {
printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
} else if (smp_num_siblings > 1 ) {
index_lsb = 0;
index_msb = 31;
if (smp_num_siblings > NR_CPUS) {
@@ -452,21 +445,34 @@ void __init detect_ht(struct cpuinfo_x86 *c)
return;
}
tmp = smp_num_siblings;
while ((tmp & 1) == 0) {
tmp >>=1 ;
index_lsb++;
}
tmp = smp_num_siblings;
while ((tmp & 0x80000000 ) == 0) {
tmp <<=1 ;
index_msb--;
}
if (index_lsb != index_msb )
if (smp_num_siblings & (smp_num_siblings - 1))
index_msb++;
phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
phys_proc_id[cpu]);
smp_num_siblings = smp_num_siblings / c->x86_num_cores;
tmp = smp_num_siblings;
index_msb = 31;
while ((tmp & 0x80000000) == 0) {
tmp <<=1 ;
index_msb--;
}
if (smp_num_siblings & (smp_num_siblings - 1))
index_msb++;
cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
if (c->x86_num_cores > 1)
printk(KERN_INFO "CPU: Processor Core ID: %d\n",
cpu_core_id[cpu]);
}
}
#endif
@@ -511,7 +517,6 @@ extern int amd_init_cpu(void);
extern int centaur_init_cpu(void);
extern int transmeta_init_cpu(void);
extern int rise_init_cpu(void);
void early_cpu_detect(void);
void __init early_cpu_init(void)
{
-1
View File
@@ -25,7 +25,6 @@ extern int get_model_name(struct cpuinfo_x86 *c);
extern void display_cacheinfo(struct cpuinfo_x86 *c);
extern void generic_identify(struct cpuinfo_x86 * c);
extern int have_cpuid_p(void);
extern void early_intel_workaround(struct cpuinfo_x86 *c);
+23
View File
@@ -74,6 +74,27 @@ static void __init Intel_errata_workarounds(struct cpuinfo_x86 *c)
}
/*
* find out the number of processor cores on the die
*/
static int __init num_cpu_cores(struct cpuinfo_x86 *c)
{
unsigned int eax;
if (c->cpuid_level < 4)
return 1;
__asm__("cpuid"
: "=a" (eax)
: "0" (4), "c" (0)
: "bx", "dx");
if (eax & 0x1f)
return ((eax >> 26) + 1);
else
return 1;
}
static void __init init_intel(struct cpuinfo_x86 *c)
{
unsigned int l2 = 0;
@@ -136,6 +157,8 @@ static void __init init_intel(struct cpuinfo_x86 *c)
if ( p )
strcpy(c->x86_model_id, p);
c->x86_num_cores = num_cpu_cores(c);
detect_ht(c);
/* Work around errata */
+2 -2
View File
@@ -179,8 +179,8 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
{
dom0_physinfo_t *pi = &op->u.physinfo;
pi->ht_per_core = ht_per_core;
pi->cores = num_online_cpus() / ht_per_core;
pi->ht_per_core = smp_num_siblings;
pi->cores = boot_cpu_data.x86_num_cores;
pi->total_pages = max_page;
pi->free_pages = avail_domheap_pages();
pi->cpu_khz = cpu_khz;
+6 -1
View File
@@ -20,6 +20,7 @@
#include <asm/desc.h>
#include <asm/shadow.h>
#include <asm/e820.h>
#include <public/acm_dom0_setup.h>
extern void dmi_scan_machine(void);
extern void generic_apic_probe(void);
@@ -66,7 +67,6 @@ boolean_param("noapic", skip_ioapic_setup);
int early_boot = 1;
int ht_per_core = 1;
cpumask_t cpu_present_map;
/* Limits of Xen heap, used to initialise the allocator. */
@@ -394,12 +394,17 @@ void __init __start_xen(multiboot_info_t *mbi)
shadow_mode_init();
/* initialize access control security module */
acm_init();
/* Create initial domain 0. */
dom0 = do_createdomain(0, 0);
if ( dom0 == NULL )
panic("Error creating domain 0\n");
set_bit(_DOMF_privileged, &dom0->domain_flags);
/* post-create hooks sets security label */
acm_post_domain0_create(dom0->domain_id);
/* Grab the DOM0 command line. */
cmdline = (char *)(mod[0].string ? __va(mod[0].string) : NULL);
+29 -3
View File
@@ -62,6 +62,8 @@ static int __initdata smp_b_stepping;
int smp_num_siblings = 1;
int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
EXPORT_SYMBOL(phys_proc_id);
int cpu_core_id[NR_CPUS]; /* Core ID of each logical CPU */
EXPORT_SYMBOL(cpu_core_id);
/* bitmap of online cpus */
cpumask_t cpu_online_map;
@@ -923,6 +925,8 @@ static int boot_cpu_logical_apicid;
void *xquad_portio;
cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
EXPORT_SYMBOL(cpu_core_map);
static void __init smp_boot_cpus(unsigned int max_cpus)
{
@@ -947,6 +951,9 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
cpus_clear(cpu_sibling_map[0]);
cpu_set(0, cpu_sibling_map[0]);
cpus_clear(cpu_core_map[0]);
cpu_set(0, cpu_core_map[0]);
/*
* If we couldn't find an SMP configuration at boot time,
* get out of here now!
@@ -959,6 +966,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
printk(KERN_NOTICE "Local APIC not detected."
" Using dummy APIC emulation.\n");
map_cpu_to_logical_apicid();
cpu_set(0, cpu_sibling_map[0]);
cpu_set(0, cpu_core_map[0]);
return;
}
@@ -1079,10 +1088,13 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
* construct cpu_sibling_map[], so that we can tell sibling CPUs
* efficiently.
*/
for (cpu = 0; cpu < NR_CPUS; cpu++)
for (cpu = 0; cpu < NR_CPUS; cpu++) {
cpus_clear(cpu_sibling_map[cpu]);
cpus_clear(cpu_core_map[cpu]);
}
for (cpu = 0; cpu < NR_CPUS; cpu++) {
struct cpuinfo_x86 *c = cpu_data + cpu;
int siblings = 0;
int i;
if (!cpu_isset(cpu, cpu_callout_map))
@@ -1092,7 +1104,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
for (i = 0; i < NR_CPUS; i++) {
if (!cpu_isset(i, cpu_callout_map))
continue;
if (phys_proc_id[cpu] == phys_proc_id[i]) {
if (cpu_core_id[cpu] == cpu_core_id[i]) {
siblings++;
cpu_set(i, cpu_sibling_map[cpu]);
}
@@ -1102,8 +1114,22 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
cpu_set(cpu, cpu_sibling_map[cpu]);
}
if (siblings != smp_num_siblings)
if (siblings != smp_num_siblings) {
printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings);
smp_num_siblings = siblings;
}
if (c->x86_num_cores > 1) {
for (i = 0; i < NR_CPUS; i++) {
if (!cpu_isset(i, cpu_callout_map))
continue;
if (phys_proc_id[cpu] == phys_proc_id[i]) {
cpu_set(i, cpu_core_map[cpu]);
}
}
} else {
cpu_core_map[cpu] = cpu_sibling_map[cpu];
}
}
if (nmi_watchdog == NMI_LOCAL_APIC)
+1
View File
@@ -751,6 +751,7 @@ ENTRY(hypercall_table)
.long do_boot_vcpu
.long do_ni_hypercall /* 25 */
.long do_mmuext_op
.long do_policy_op /* 27 */
.rept NR_hypercalls-((.-hypercall_table)/4)
.long do_ni_hypercall
.endr
+2 -2
View File
@@ -1,8 +1,8 @@
include $(BASEDIR)/Rules.mk
ifeq ($(TARGET_ARCH),ia64)
OBJS := $(subst dom_mem_ops.o,,$(OBJS))
ifeq ($(TARGET_ARCH),ia64)
#OBJS := $(subst dom_mem_ops.o,,$(OBJS))
OBJS := $(subst grant_table.o,,$(OBJS))
endif
+16 -3
View File
@@ -19,6 +19,7 @@
#include <asm/current.h>
#include <public/dom0_ops.h>
#include <public/sched_ctl.h>
#include <acm/acm_hooks.h>
extern long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op);
extern void arch_getdomaininfo_ctxt(
@@ -91,6 +92,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
{
long ret = 0;
dom0_op_t curop, *op = &curop;
void *ssid = NULL; /* save security ptr between pre and post/fail hooks */
if ( !IS_PRIV(current->domain) )
return -EPERM;
@@ -101,6 +103,9 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
if ( op->interface_version != DOM0_INTERFACE_VERSION )
return -EACCES;
if ( acm_pre_dom0_op(op, &ssid) )
return -EACCES;
switch ( op->cmd )
{
@@ -184,8 +189,8 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
* domains will all share the second HT of each CPU. Since dom0 is on
* CPU 0, we favour high numbered CPUs in the event of a tie.
*/
pro = ht_per_core - 1;
for ( i = pro; i < num_online_cpus(); i += ht_per_core )
pro = smp_num_siblings - 1;
for ( i = pro; i < num_online_cpus(); i += smp_num_siblings )
if ( cnt[i] <= cnt[pro] )
pro = i;
@@ -357,6 +362,11 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
((d->domain_flags & DOMF_shutdown) ? DOMFLAGS_SHUTDOWN : 0) |
d->shutdown_code << DOMFLAGS_SHUTDOWNSHIFT;
if (d->ssid != NULL)
op->u.getdomaininfo.ssidref = ((struct acm_ssid_domain *)d->ssid)->ssidref;
else
op->u.getdomaininfo.ssidref = ACM_DEFAULT_SSID;
op->u.getdomaininfo.tot_pages = d->tot_pages;
op->u.getdomaininfo.max_pages = d->max_pages;
op->u.getdomaininfo.shared_info_frame =
@@ -493,7 +503,10 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
ret = arch_do_dom0_op(op,u_dom0_op);
}
if (!ret)
acm_post_dom0_op(op, ssid);
else
acm_fail_dom0_op(op, ssid);
return ret;
}
+4
View File
@@ -26,6 +26,7 @@
#include <public/xen.h>
#include <public/event_channel.h>
#include <acm/acm_hooks.h>
#define bucket_from_port(d,p) \
((d)->evtchn[(p)/EVTCHNS_PER_BUCKET])
@@ -587,6 +588,9 @@ long do_event_channel_op(evtchn_op_t *uop)
if ( copy_from_user(&op, uop, sizeof(op)) != 0 )
return -EFAULT;
if (acm_pre_event_channel(&op))
return -EACCES;
switch ( op.cmd )
{
case EVTCHNOP_alloc_unbound:
+6
View File
@@ -30,6 +30,7 @@
#include <xen/sched.h>
#include <xen/shadow.h>
#include <xen/mm.h>
#include <acm/acm_hooks.h>
#define PIN_FAIL(_lbl, _rc, _f, _a...) \
do { \
@@ -357,6 +358,11 @@ __gnttab_map_grant_ref(
return GNTST_bad_gntref;
}
if (acm_pre_grant_map_ref(dom)) {
(void)__put_user(GNTST_permission_denied, &uop->handle);
return GNTST_permission_denied;
}
if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
unlikely(ld == rd) )
{
+33 -8
View File
@@ -1,10 +1,7 @@
/******************************************************************************
* kernel.c
*
* This file should contain architecture-independent bootstrap and low-level
* help routines. It's a bit x86/PC specific right now!
*
* Copyright (c) 2002-2003 K A Fraser
* Copyright (c) 2002-2005 K A Fraser
*/
#include <xen/config.h>
@@ -14,6 +11,7 @@
#include <xen/compile.h>
#include <xen/sched.h>
#include <asm/current.h>
#include <public/version.h>
void cmdline_parse(char *cmdline)
{
@@ -83,11 +81,38 @@ void cmdline_parse(char *cmdline)
* Simple hypercalls.
*/
long do_xen_version(int cmd)
long do_xen_version(int cmd, void *arg)
{
if ( cmd != 0 )
return -ENOSYS;
return (XEN_VERSION<<16) | (XEN_SUBVERSION);
switch ( cmd )
{
case XENVER_version:
{
return (XEN_VERSION<<16) | (XEN_SUBVERSION);
}
case XENVER_extraversion:
{
char extraversion[16];
safe_strcpy(extraversion, XEN_EXTRAVERSION);
if ( copy_to_user(arg, extraversion, sizeof(extraversion)) )
return -EFAULT;
return 0;
}
case XENVER_compile_info:
{
struct xen_compile_info info;
safe_strcpy(info.compiler, XEN_COMPILER);
safe_strcpy(info.compile_by, XEN_COMPILE_BY);
safe_strcpy(info.compile_domain, XEN_COMPILE_DOMAIN);
safe_strcpy(info.compile_date, XEN_COMPILE_DATE);
if ( copy_to_user(arg, &info, sizeof(info)) )
return -EFAULT;
return 0;
}
}
return -ENOSYS;
}
long do_vm_assist(unsigned int cmd, unsigned int type)
+117
View File
@@ -0,0 +1,117 @@
/******************************************************************************
*policy_ops.c
*
* Copyright (C) 2005 IBM Corporation
*
* Author:
* Reiner Sailer <sailer@watson.ibm.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*
* Process policy command requests from guest OS.
*
*/
#include <xen/config.h>
#include <xen/types.h>
#include <xen/lib.h>
#include <xen/mm.h>
#include <public/policy_ops.h>
#include <xen/sched.h>
#include <xen/event.h>
#include <xen/trace.h>
#include <xen/console.h>
#include <asm/shadow.h>
#include <public/sched_ctl.h>
#include <acm/acm_hooks.h>
/* function prototypes defined in acm/acm_policy.c */
int acm_set_policy(void *buf, u16 buf_size, u16 policy);
int acm_get_policy(void *buf, u16 buf_size);
int acm_dump_statistics(void *buf, u16 buf_size);
typedef enum policyoperation {
POLICY, /* access to policy interface (early drop) */
GETPOLICY, /* dump policy cache */
SETPOLICY, /* set policy cache (controls security) */
DUMPSTATS /* dump policy statistics */
} policyoperation_t;
int
acm_authorize_policyops(struct domain *d, policyoperation_t pops)
{
/* currently, all policy management functions are restricted to privileged domains,
* soon we will introduce finer-grained privileges for policy operations
*/
if (!IS_PRIV(d)) {
printk("%s: Policy management authorization denied ERROR!\n", __func__);
return ACM_ACCESS_DENIED;
}
return ACM_ACCESS_PERMITTED;
}
long do_policy_op(policy_op_t *u_policy_op)
{
long ret = 0;
policy_op_t curop, *op = &curop;
/* check here policy decision for policy commands */
/* for now allow DOM0 only, later indepedently */
if (acm_authorize_policyops(current->domain, POLICY))
return -EACCES;
if ( copy_from_user(op, u_policy_op, sizeof(*op)) )
return -EFAULT;
if ( op->interface_version != POLICY_INTERFACE_VERSION )
return -EACCES;
switch ( op->cmd )
{
case POLICY_SETPOLICY:
{
if (acm_authorize_policyops(current->domain, SETPOLICY))
return -EACCES;
printkd("%s: setting policy.\n", __func__);
ret = acm_set_policy(op->u.setpolicy.pushcache, op->u.setpolicy.pushcache_size, op->u.setpolicy.policy_type);
if (ret == ACM_OK)
ret = 0;
else
ret = -ESRCH;
}
break;
case POLICY_GETPOLICY:
{
if (acm_authorize_policyops(current->domain, GETPOLICY))
return -EACCES;
printkd("%s: getting policy.\n", __func__);
ret = acm_get_policy(op->u.getpolicy.pullcache, op->u.getpolicy.pullcache_size);
if (ret == ACM_OK)
ret = 0;
else
ret = -ESRCH;
}
break;
case POLICY_DUMPSTATS:
{
if (acm_authorize_policyops(current->domain, DUMPSTATS))
return -EACCES;
printkd("%s: dumping statistics.\n", __func__);
ret = acm_dump_statistics(op->u.dumpstats.pullcache, op->u.dumpstats.pullcache_size);
if (ret == ACM_OK)
ret = 0;
else
ret = -ESRCH;
}
break;
default:
ret = -ESRCH;
}
return ret;
}
+117
View File
@@ -0,0 +1,117 @@
/****************************************************************
* acm_core.h
*
* Copyright (C) 2005 IBM Corporation
*
* Author:
* Reiner Sailer <sailer@watson.ibm.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*
* sHype header file describing core data types and constants
* for the access control module and relevant policies
*
*/
#ifndef _ACM_CORE_H
#define _ACM_CORE_H
#include <xen/spinlock.h>
#include <public/acm.h>
#include <public/policy_ops.h>
/* Xen-internal representation of the binary policy */
struct acm_binary_policy {
u16 primary_policy_code;
u16 secondary_policy_code;
void *primary_binary_policy;
void *secondary_binary_policy;
};
struct chwall_binary_policy {
u16 max_types;
u16 max_ssidrefs;
u16 max_conflictsets;
domaintype_t *ssidrefs; /* [max_ssidrefs][max_types] */
domaintype_t *conflict_aggregate_set; /* [max_types] */
domaintype_t *running_types; /* [max_types] */
domaintype_t *conflict_sets; /* [max_conflictsets][max_types]*/
};
struct ste_binary_policy {
u16 max_types;
u16 max_ssidrefs;
domaintype_t *ssidrefs; /* [max_ssidrefs][max_types] */
atomic_t ec_eval_count, gt_eval_count;
atomic_t ec_denied_count, gt_denied_count;
atomic_t ec_cachehit_count, gt_cachehit_count;
};
/* global acm policy */
extern struct acm_binary_policy acm_bin_pol;
extern struct chwall_binary_policy chwall_bin_pol;
extern struct ste_binary_policy ste_bin_pol;
/* use the lock when reading / changing binary policy ! */
extern rwlock_t acm_bin_pol_rwlock;
/* subject and object type definitions */
enum acm_datatype { DOMAIN };
/* defines number of access decisions to other domains can be cached
* one entry per domain, TE does not distinguish evtchn or grant_table */
#define ACM_TE_CACHE_SIZE 8
enum acm_ste_flag { VALID, FREE };
/* cache line:
* if cache_line.valid==VALID, then
* STE decision is cached as "permitted"
* on domain cache_line.id
*/
struct acm_ste_cache_line {
enum acm_ste_flag valid;
domid_t id;
};
/* general definition of a subject security id */
struct acm_ssid_domain {
enum acm_datatype datatype; /* type of subject (e.g., partition) */
ssidref_t ssidref; /* combined security reference */
void *primary_ssid; /* primary policy ssid part (e.g. chinese wall) */
void *secondary_ssid; /* secondary policy ssid part (e.g. type enforcement) */
struct domain *subject; /* backpointer to subject structure */
domid_t domainid; /* replicate id */
};
/* chinese wall ssid type */
struct chwall_ssid {
ssidref_t chwall_ssidref;
};
/* simple type enforcement ssid type */
struct ste_ssid {
ssidref_t ste_ssidref;
struct acm_ste_cache_line ste_cache[ACM_TE_CACHE_SIZE]; /* decision cache */
};
/* macros to access ssidref for primary / secondary policy
* primary ssidref = lower 16 bit
* secondary ssidref = higher 16 bit
*/
#define GET_SSIDREF(POLICY, ssidref) \
((POLICY) == acm_bin_pol.primary_policy_code) ? \
((ssidref) & 0xffff) : ((ssidref) >> 16)
/* macros to access ssid pointer for primary / secondary policy */
#define GET_SSIDP(POLICY, ssid) \
((POLICY) == acm_bin_pol.primary_policy_code) ? \
((ssid)->primary_ssid) : ((ssid)->secondary_ssid)
/* protos */
int acm_init_domain_ssid(domid_t id, ssidref_t ssidref);
int acm_free_domain_ssid(struct acm_ssid_domain *ssid);
#endif
+88
View File
@@ -0,0 +1,88 @@
/****************************************************************
* acm_endian.h
*
* Copyright (C) 2005 IBM Corporation
*
* Author:
* Stefan Berger <stefanb@watson.ibm.com>
*
* Contributions:
* Reiner Sailer <sailer@watson.ibm.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*
* sHype header file defining endian-dependent functions for the
* big-endian policy interface
*
*/
#ifndef _ACM_ENDIAN_H
#define _ACM_ENDIAN_H
/* don't use these functions in performance critical sections! */
/* set during initialization by testing */
extern u8 little_endian;
static inline u32 ntohl(u32 x)
{
if (little_endian)
return
( (((x) >> 24) & 0xff )|
(((x) >> 8) & 0xff00 )|
(((x) << 8) & 0xff0000 )|
(((x) << 24) & 0xff000000) );
else
return x;
}
static inline u16 ntohs(u16 x)
{
if (little_endian)
return
( (((x) >> 8) & 0xff )|
(((x) << 8) & 0xff00 ) );
else
return x;
}
#define htonl(x) ntohl(x)
#define htons(x) ntohs(x)
static inline void arrcpy16(u16 *dest, const u16 *src, size_t n)
{
unsigned int i = 0;
while (i < n) {
dest[i] = htons(src[i]);
i++;
}
}
static inline void arrcpy32(u32 *dest, const u32 *src, size_t n)
{
unsigned int i = 0;
while (i < n) {
dest[i] = htonl(src[i]);
i++;
}
}
static inline void arrcpy(void *dest, const void *src, unsigned int elsize, size_t n)
{
switch (elsize) {
case sizeof(u16):
arrcpy16((u16 *)dest, (u16 *)src, n);
break;
case sizeof(u32):
arrcpy32((u32 *)dest, (u32 *)src, n);
break;
default:
memcpy(dest, src, elsize*n);
}
}
#endif
+337
View File
@@ -0,0 +1,337 @@
/****************************************************************
* acm_hooks.h
*
* Copyright (C) 2005 IBM Corporation
*
* Author:
* Reiner Sailer <sailer@watson.ibm.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*
* acm header file implementing the global (policy-independent)
* sHype hooks that are called throughout Xen.
*
*/
#ifndef _ACM_HOOKS_H
#define _ACM_HOOKS_H
#include <xen/config.h>
#include <xen/errno.h>
#include <xen/types.h>
#include <xen/lib.h>
#include <xen/delay.h>
#include <xen/sched.h>
#include <public/acm.h>
#include <acm/acm_core.h>
#include <public/dom0_ops.h>
#include <public/event_channel.h>
#include <asm/current.h>
/* if ACM_TRACE_MODE defined, all hooks should
* print a short trace message */
/* #define ACM_TRACE_MODE */
#ifdef ACM_TRACE_MODE
# define traceprintk(fmt, args...) printk(fmt,## args)
#else
# define traceprintk(fmt, args...)
#endif
/* global variables */
extern struct acm_operations *acm_primary_ops;
extern struct acm_operations *acm_secondary_ops;
/**********************************************************************************************
* HOOK structure and meaning (justifies a few words about our model):
*
* General idea: every policy-controlled system operation is reflected in a
* transaction in the system's security state
*
* Keeping the security state consistent requires "atomic" transactions.
* The name of the hooks to place around policy-controlled transactions
* reflects this. If authorizations do not involve security state changes,
* then and only then POST and FAIL hooks remain empty since we don't care
* about the eventual outcome of the operation from a security viewpoint.
*
* PURPOSE of hook types:
* ======================
* PRE-Hooks
* a) general authorization to guard a controlled system operation
* b) prepare security state change (means: fail hook must be able to "undo" this)
*
* POST-Hooks
* a) commit prepared state change
*
* FAIL-Hooks
* a) roll-back prepared security state change from PRE-Hook
*
*
* PLACEMENT of hook types:
* ========================
* PRE-Hooks must be called:
* a) before a guarded/controlled system operation is started
* (return is ACM_ACCESS_PERMITTED or ACM_ACCESS_DENIED or error)
* --> operation must be aborted if return is != ACM_ACCESS_PERMITTED
*
* POST-Hooks must be called:
* a) after successful transaction (no return value; commit shall never fail)
*
* FAIL-Hooks must be called:
* a) if system transaction (operation) fails somewhen after calling the PRE-hook
* (obviously the POST-Hook is not called in this case)
* b) if another (secondary) policy denies access in its PRE-Hook
* (policy layering is useful but requires additional handling)
*
*
*
* Hook model from a security transaction viewpoint:
*
* start-sys-ops--> prepare ----succeed-----> commit --> sys-ops success
* (pre-hook) \ (post-hook)
* \
* fail
* \
* \
* roll-back
* (fail-hook)
* \
* sys-ops error
*
*************************************************************************************************/
struct acm_operations {
/* policy management functions (must always be defined!) */
int (*init_domain_ssid) (void **ssid, ssidref_t ssidref);
void (*free_domain_ssid) (void *ssid);
int (*dump_binary_policy) (u8 *buffer, u16 buf_size);
int (*set_binary_policy) (u8 *buffer, u16 buf_size);
int (*dump_statistics) (u8 *buffer, u16 buf_size);
/* domain management control hooks (can be NULL) */
int (*pre_domain_create) (void *subject_ssid, ssidref_t ssidref);
void (*post_domain_create) (domid_t domid, ssidref_t ssidref);
void (*fail_domain_create) (void *subject_ssid, ssidref_t ssidref);
void (*post_domain_destroy) (void *object_ssid, domid_t id);
/* event channel control hooks (can be NULL) */
int (*pre_eventchannel_unbound) (domid_t id);
void (*fail_eventchannel_unbound) (domid_t id);
int (*pre_eventchannel_interdomain) (domid_t id1, domid_t id2);
int (*fail_eventchannel_interdomain) (domid_t id1, domid_t id2);
/* grant table control hooks (can be NULL) */
int (*pre_grant_map_ref) (domid_t id);
void (*fail_grant_map_ref) (domid_t id);
int (*pre_grant_setup) (domid_t id);
void (*fail_grant_setup) (domid_t id);
};
static inline int acm_pre_domain_create (void *subject_ssid, ssidref_t ssidref)
{
if ((acm_primary_ops->pre_domain_create != NULL) &&
acm_primary_ops->pre_domain_create (subject_ssid, ssidref))
return ACM_ACCESS_DENIED;
else if ((acm_secondary_ops->pre_domain_create != NULL) &&
acm_secondary_ops->pre_domain_create (subject_ssid, ssidref)) {
/* roll-back primary */
if (acm_primary_ops->fail_domain_create != NULL)
acm_primary_ops->fail_domain_create (subject_ssid, ssidref);
return ACM_ACCESS_DENIED;
} else
return ACM_ACCESS_PERMITTED;
}
static inline void acm_post_domain_create (domid_t domid, ssidref_t ssidref)
{
if (acm_primary_ops->post_domain_create != NULL)
acm_primary_ops->post_domain_create (domid, ssidref);
if (acm_secondary_ops->post_domain_create != NULL)
acm_secondary_ops->post_domain_create (domid, ssidref);
}
static inline void acm_fail_domain_create (void *subject_ssid, ssidref_t ssidref)
{
if (acm_primary_ops->fail_domain_create != NULL)
acm_primary_ops->fail_domain_create (subject_ssid, ssidref);
if (acm_secondary_ops->fail_domain_create != NULL)
acm_secondary_ops->fail_domain_create (subject_ssid, ssidref);
}
static inline void acm_post_domain_destroy (void *object_ssid, domid_t id)
{
if (acm_primary_ops->post_domain_destroy != NULL)
acm_primary_ops->post_domain_destroy (object_ssid, id);
if (acm_secondary_ops->post_domain_destroy != NULL)
acm_secondary_ops->post_domain_destroy (object_ssid, id);
return;
}
/* event channel ops */
static inline int acm_pre_eventchannel_unbound (domid_t id)
{
if ((acm_primary_ops->pre_eventchannel_unbound != NULL) &&
acm_primary_ops->pre_eventchannel_unbound (id))
return ACM_ACCESS_DENIED;
else if ((acm_secondary_ops->pre_eventchannel_unbound != NULL) &&
acm_secondary_ops->pre_eventchannel_unbound (id)) {
/* roll-back primary */
if (acm_primary_ops->fail_eventchannel_unbound != NULL)
acm_primary_ops->fail_eventchannel_unbound (id);
return ACM_ACCESS_DENIED;
} else
return ACM_ACCESS_PERMITTED;
}
static inline int acm_pre_eventchannel_interdomain (domid_t id1, domid_t id2)
{
if ((acm_primary_ops->pre_eventchannel_interdomain != NULL) &&
acm_primary_ops->pre_eventchannel_interdomain (id1, id2))
return ACM_ACCESS_DENIED;
else if ((acm_secondary_ops->pre_eventchannel_interdomain != NULL) &&
acm_secondary_ops->pre_eventchannel_interdomain (id1, id2)) {
/* roll-back primary */
if (acm_primary_ops->fail_eventchannel_interdomain != NULL)
acm_primary_ops->fail_eventchannel_interdomain (id1, id2);
return ACM_ACCESS_DENIED;
} else
return ACM_ACCESS_PERMITTED;
}
/************ Xen inline hooks ***************/
/* small macro to make the hooks more readable
* (eliminates hooks if NULL policy is active)
*/
#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
static inline int acm_pre_dom0_op(dom0_op_t *op, void **ssid)
{ return 0; }
#else
static inline int acm_pre_dom0_op(dom0_op_t *op, void **ssid)
{
int ret = -EACCES;
struct domain *d;
switch(op->cmd) {
case DOM0_CREATEDOMAIN:
ret = acm_pre_domain_create(current->domain->ssid, op->u.createdomain.ssidref);
break;
case DOM0_DESTROYDOMAIN:
d = find_domain_by_id(op->u.destroydomain.domain);
if (d != NULL) {
*ssid = d->ssid; /* save for post destroy when d is gone */
/* no policy-specific hook */
put_domain(d);
ret = 0;
}
break;
default:
ret = 0; /* ok */
}
return ret;
}
#endif
#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
static inline void acm_post_dom0_op(dom0_op_t *op, void *ssid)
{ return; }
#else
static inline void acm_post_dom0_op(dom0_op_t *op, void *ssid)
{
switch(op->cmd) {
case DOM0_CREATEDOMAIN:
/* initialialize shared sHype security labels for new domain */
acm_init_domain_ssid(op->u.createdomain.domain, op->u.createdomain.ssidref);
acm_post_domain_create(op->u.createdomain.domain, op->u.createdomain.ssidref);
break;
case DOM0_DESTROYDOMAIN:
acm_post_domain_destroy(ssid, op->u.destroydomain.domain);
/* free security ssid for the destroyed domain (also if running null policy */
acm_free_domain_ssid((struct acm_ssid_domain *)ssid);
break;
}
}
#endif
#if (ACM_USE_SECURITY_POLICy == ACM_NULL_POLICY)
static inline void acm_fail_dom0_op(dom0_op_t *op, void *ssid)
{ return; }
#else
static inline void acm_fail_dom0_op(dom0_op_t *op, void *ssid)
{
switch(op->cmd) {
case DOM0_CREATEDOMAIN:
acm_fail_domain_create(current->domain->ssid, op->u.createdomain.ssidref);
break;
}
}
#endif
#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
static inline int acm_pre_event_channel(evtchn_op_t *op)
{ return 0; }
#else
static inline int acm_pre_event_channel(evtchn_op_t *op)
{
int ret = -EACCES;
switch(op->cmd) {
case EVTCHNOP_alloc_unbound:
ret = acm_pre_eventchannel_unbound(op->u.alloc_unbound.dom);
break;
case EVTCHNOP_bind_interdomain:
ret = acm_pre_eventchannel_interdomain(op->u.bind_interdomain.dom1, op->u.bind_interdomain.dom2);
break;
default:
ret = 0; /* ok */
}
return ret;
}
#endif
#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
static inline int acm_pre_grant_map_ref(domid_t id)
{ return 0; }
#else
static inline int acm_pre_grant_map_ref (domid_t id)
{
if ((acm_primary_ops->pre_grant_map_ref != NULL) &&
acm_primary_ops->pre_grant_map_ref (id))
return ACM_ACCESS_DENIED;
else if ((acm_secondary_ops->pre_grant_map_ref != NULL) &&
acm_secondary_ops->pre_grant_map_ref (id)) {
/* roll-back primary */
if (acm_primary_ops->fail_grant_map_ref != NULL)
acm_primary_ops->fail_grant_map_ref (id);
return ACM_ACCESS_DENIED;
} else
return ACM_ACCESS_PERMITTED;
}
#endif
#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
static inline int acm_pre_grant_setup(domid_t id)
{ return 0; }
#else
static inline int acm_pre_grant_setup (domid_t id)
{
if ((acm_primary_ops->pre_grant_setup != NULL) &&
acm_primary_ops->pre_grant_setup (id))
return ACM_ACCESS_DENIED;
else if ((acm_secondary_ops->pre_grant_setup != NULL) &&
acm_secondary_ops->pre_grant_setup (id)) {
/* roll-back primary */
if (acm_primary_ops->fail_grant_setup != NULL)
acm_primary_ops->fail_grant_setup (id);
return ACM_ACCESS_DENIED;
} else
return ACM_ACCESS_PERMITTED;
}
#endif
#endif
+3 -2
View File
@@ -177,8 +177,7 @@ void sort_main_extable(void);
// see include/asm-x86/atomic.h (different from standard linux)
#define _atomic_set(v,i) (((v).counter) = (i))
#define _atomic_read(v) ((v).counter)
// FIXME following needs work
#define atomic_compareandswap(old, new, v) old
#define atomic_compareandswap(old, new, v) ((atomic_t){ cmpxchg(v, _atomic_read(old), _atomic_read(new)) })
// see include/asm-ia64/mm.h, handle remaining pfn_info uses until gone
#define pfn_info page
@@ -227,6 +226,8 @@ struct screen_info { };
#define FORCE_CRASH() asm("break 0;;");
#define dummy() dummy_called(__FUNCTION__)
// these declarations got moved at some point, find a better place for them
extern int ht_per_core;
+11 -4
View File
@@ -2,18 +2,17 @@
#define __ASM_DOMAIN_H__
#include <linux/thread_info.h>
#include <asm/tlb.h>
#ifdef CONFIG_VTI
#include <asm/vmx_vpd.h>
#include <asm/vmmu.h>
#include <asm/regionreg.h>
#include <public/arch-ia64.h>
#endif // CONFIG_VTI
#include <xen/list.h>
extern void arch_do_createdomain(struct vcpu *);
extern int arch_final_setup_guestos(
struct vcpu *, struct vcpu_guest_context *);
extern void domain_relinquish_resources(struct domain *);
#ifdef CONFIG_VTI
@@ -36,7 +35,15 @@ struct arch_domain {
int imp_va_msb;
ia64_rr emul_phy_rr0;
ia64_rr emul_phy_rr4;
u64 *pmt; /* physical to machine table */
unsigned long *pmt; /* physical to machine table */
/*
* max_pfn is the maximum page frame in guest physical space, including
* inter-middle I/O ranges and memory holes. This is different with
* max_pages in domain struct, which indicates maximum memory size
*/
unsigned long max_pfn;
unsigned int section_nr;
mm_section_t *sections; /* Describe memory hole except for Dom0 */
#endif //CONFIG_VTI
u64 xen_vastart;
u64 xen_vaend;
+16
View File
@@ -0,0 +1,16 @@
/******************************************************************************
* event.h
*
* A nice interface for passing asynchronous events to guest OSes.
* (architecture-dependent part)
*
*/
#ifndef __ASM_EVENT_H__
#define __ASM_EVENT_H__
static inline void evtchn_notify(struct vcpu *v)
{
}
#endif
+87 -53
View File
@@ -27,43 +27,12 @@ typedef unsigned long page_flags_t;
/*
* Per-page-frame information.
*
* Every architecture must ensure the following:
* 1. 'struct pfn_info' contains a 'struct list_head list'.
* 2. Provide a PFN_ORDER() macro for accessing the order of a free page.
*/
//FIXME: This can go away when common/dom0_ops.c is fully arch-independent
#if 0
struct pfn_info
{
/* Each frame can be threaded onto a doubly-linked list. */
struct list_head list;
/* Context-dependent fields follow... */
union {
/* Page is in use by a domain. */
struct {
/* Owner of this page. */
struct domain *domain;
/* Reference count and various PGC_xxx flags and fields. */
u32 count_info;
/* Type reference count and various PGT_xxx flags and fields. */
u32 type_info;
} inuse;
/* Page is on a free list. */
struct {
/* Mask of possibly-tainted TLBs. */
unsigned long cpu_mask;
/* Must be at same offset as 'u.inuse.count_flags'. */
u32 __unavailable;
/* Order-size of the free chunk this page is the head of. */
u8 order;
} free;
} u;
/* Timestamp from 'TLB clock', used to reduce need for safety flushes. */
u32 tlbflush_timestamp;
};
#endif
#define PFN_ORDER(_pfn) ((_pfn)->u.free.order)
struct page
{
@@ -82,7 +51,7 @@ struct page
/* Page is in use by a domain. */
struct {
/* Owner of this page. */
u64 _domain;
u32 _domain;
/* Type reference count and various PGT_xxx flags and fields. */
u32 type_info;
} inuse;
@@ -104,37 +73,49 @@ struct page
#define set_page_count(p,v) atomic_set(&(p)->_count, v - 1)
//FIXME: These can go away when common/dom0_ops.c is fully arch-independent
/* The following page types are MUTUALLY EXCLUSIVE. */
/* Still small set of flags defined by far on IA-64 */
/* The following page types are MUTUALLY EXCLUSIVE. */
#define PGT_none (0<<29) /* no special uses of this page */
#define PGT_l1_page_table (1<<29) /* using this page as an L1 page table? */
#define PGT_l2_page_table (2<<29) /* using this page as an L2 page table? */
#define PGT_l3_page_table (3<<29) /* using this page as an L3 page table? */
#define PGT_l4_page_table (4<<29) /* using this page as an L4 page table? */
#define PGT_gdt_page (5<<29) /* using this page in a GDT? */
#define PGT_ldt_page (6<<29) /* using this page in an LDT? */
#define PGT_writeable_page (7<<29) /* has writable mappings of this page? */
#define PGT_type_mask (7<<29) /* Bits 29-31. */
#define PGT_writeable_page (5<<29) /* has writable mappings of this page? */
#define PGT_type_mask (5<<29) /* Bits 29-31. */
/* Has this page been validated for use as its current type? */
#define _PGT_validated 28
#define PGT_validated (1<<_PGT_validated)
/* 28-bit count of uses of this frame as its current type. */
#define PGT_count_mask ((1<<28)-1)
/* Owning guest has pinned this page to its current type? */
#define _PGT_pinned 27
#define PGT_pinned (1U<<_PGT_pinned)
/* 27-bit count of uses of this frame as its current type. */
#define PGT_count_mask ((1U<<27)-1)
/* Cleared when the owning guest 'frees' this page. */
#define _PGC_allocated 31
#define PGC_allocated (1U<<_PGC_allocated)
#define PFN_ORDER(_pfn) ((_pfn)->u.free.order)
/* Set when the page is used as a page table */
#define _PGC_page_table 30
#define PGC_page_table (1U<<_PGC_page_table)
/* 30-bit count of references to this frame. */
#define PGC_count_mask ((1U<<30)-1)
#define IS_XEN_HEAP_FRAME(_pfn) ((page_to_phys(_pfn) < xenheap_phys_end) \
&& (page_to_phys(_pfn) >= xen_pstart))
#define pickle_domptr(_d) ((u64)(_d))
#define unpickle_domptr(_d) ((struct domain*)(_d))
static inline struct domain *unpickle_domptr(u32 _d)
{ return (_d == 0) ? NULL : __va(_d); }
static inline u32 pickle_domptr(struct domain *_d)
{ return (_d == NULL) ? 0 : (u32)__pa(_d); }
#define page_get_owner(_p) (unpickle_domptr((_p)->u.inuse._domain))
#define page_set_owner(_p, _d) ((_p)->u.inuse._domain = pickle_domptr(_d))
/* Dummy now */
#define SHARE_PFN_WITH_DOMAIN(_pfn, _dom) do { } while (0)
extern struct pfn_info *frame_table;
extern unsigned long frame_table_size;
extern struct list_head free_list;
@@ -151,16 +132,46 @@ void add_to_domain_alloc_list(unsigned long ps, unsigned long pe);
static inline void put_page(struct pfn_info *page)
{
dummy();
u32 nx, x, y = page->count_info;
do {
x = y;
nx = x - 1;
}
while (unlikely((y = cmpxchg(&page->count_info, x, nx)) != x));
if (unlikely((nx & PGC_count_mask) == 0))
free_domheap_page(page);
}
/* count_info and ownership are checked atomically. */
static inline int get_page(struct pfn_info *page,
struct domain *domain)
{
dummy();
u64 x, nx, y = *((u64*)&page->count_info);
u32 _domain = pickle_domptr(domain);
do {
x = y;
nx = x + 1;
if (unlikely((x & PGC_count_mask) == 0) || /* Not allocated? */
unlikely((nx & PGC_count_mask) == 0) || /* Count overflow? */
unlikely((x >> 32) != _domain)) { /* Wrong owner? */
DPRINTK("Error pfn %lx: rd=%p, od=%p, caf=%08x, taf=%08x\n",
page_to_pfn(page), domain, unpickle_domptr(d),
x, page->u.inuse.typeinfo);
return 0;
}
}
while(unlikely(y = cmpxchg(&page->count_info, x, nx)) != x);
return 1;
}
/* No type info now */
#define put_page_and_type(page) put_page((page))
#define get_page_and_type(page, domain, type) get_page((page))
#define set_machinetophys(_mfn, _pfn) do { } while(0);
#ifdef MEMORY_GUARD
@@ -364,17 +375,40 @@ extern unsigned long *mpt_table;
#undef machine_to_phys_mapping
#define machine_to_phys_mapping mpt_table
#define INVALID_M2P_ENTRY (~0U)
#define VALID_M2P(_e) (!((_e) & (1U<<63)))
#define IS_INVALID_M2P_ENTRY(_e) (!VALID_M2P(_e))
/* If pmt table is provided by control pannel later, we need __get_user
* here. However if it's allocated by HV, we should access it directly
*/
#define phys_to_machine_mapping(d, gpfn) \
((d) == dom0 ? gpfn : (d)->arch.pmt[(gpfn)])
#define phys_to_machine_mapping(d, gpfn) \
((d) == dom0 ? gpfn : \
(gpfn <= d->arch.max_pfn ? (d)->arch.pmt[(gpfn)] : \
INVALID_MFN))
#define __mfn_to_gpfn(_d, mfn) \
machine_to_phys_mapping[(mfn)]
#define __gpfn_to_mfn(_d, gpfn) \
phys_to_machine_mapping((_d), (gpfn))
#define __gpfn_invalid(_d, gpfn) \
(__gpfn_to_mfn((_d), (gpfn)) & GPFN_INV_MASK)
#define __gpfn_valid(_d, gpfn) !__gpfn_invalid(_d, gpfn)
/* Return I/O type if trye */
#define __gpfn_is_io(_d, gpfn) \
(__gpfn_valid(_d, gpfn) ? \
(__gpfn_to_mfn((_d), (gpfn)) & GPFN_IO_MASK) : 0)
#define __gpfn_is_mem(_d, gpfn) \
(__gpfn_valid(_d, gpfn) ? \
((__gpfn_to_mfn((_d), (gpfn)) & GPFN_IO_MASK) == GPFN_MEM) : 0)
#define __gpa_to_mpa(_d, gpa) \
((__gpfn_to_mfn((_d),(gpa)>>PAGE_SHIFT)<<PAGE_SHIFT)|((gpa)&~PAGE_MASK))
#endif // CONFIG_VTI
#endif /* __ASM_IA64_MM_H__ */
+5 -5
View File
@@ -39,11 +39,11 @@ typedef struct {
typedef union {
unsigned long value;
struct {
uint64_t ve : 1;
uint64_t rv1 : 1;
uint64_t ps : 6;
uint64_t rid : 24;
uint64_t rv2 : 32;
unsigned long ve : 1;
unsigned long rv1 : 1;
unsigned long ps : 6;
unsigned long rid : 24;
unsigned long rv2 : 32;
};
} rr_t;
#endif // CONFIG_VTI
+2 -2
View File
@@ -23,8 +23,8 @@ typedef struct pt_regs REGS;
#define PRIVOP_ADDR_COUNT
#ifdef PRIVOP_ADDR_COUNT
#define _RSM 0
#define _SSM 1
#define _GET_IFA 0
#define _THASH 1
#define PRIVOP_COUNT_NINSTS 2
#define PRIVOP_COUNT_NADDRS 30
+15 -2
View File
@@ -139,13 +139,21 @@ CC_##Name:; \
mov r31 = pr; \
mov r16 = cr.ifa; \
movl r30 = int_counts; \
;; \
extr.u r17=r16,59,5 \
;; \
cmp.eq p6,p0=0x1e,r17; \
(p6) br.cond.spnt .Alt_##Name \
;; \
cmp.eq p6,p0=0x1d,r17; \
(p6) br.cond.spnt .Alt_##Name \
;; \
thash r28 = r16; \
adds r30 = CAUSE_VHPT_CC_HANDLED << 3, r30; \
;; \
ttag r19 = r16; \
ld8 r27 = [r30]; \
adds r17 = VLE_CCHAIN_OFFSET, r28; \
ld8 r27 = [r30]; \
adds r17 = VLE_CCHAIN_OFFSET, r28; \
;; \
ld8 r17 = [r17]; \
;; \
@@ -192,6 +200,11 @@ CC_##Name:; \
rfi; \
;; \
\
.Alt_##Name:; \
mov pr = r31, 0x1ffff; \
;; \
br.cond.sptk late_alt_##Name \
;; \
.Out_##Name:; \
mov pr = r31, 0x1ffff; \
;; \
+15 -16
View File
@@ -28,13 +28,13 @@
#include "public/xen.h"
#include "asm/tlb.h"
#define THASH_TLB_TR 0
#define THASH_TLB_TC 1
#define THASH_TLB_FM 2 // foreign map
//#define THASH_TLB_TR 0
//#define THASH_TLB_TC 1
#define THASH_SECTION_TR (1<<0)
#define THASH_SECTION_TC (1<<1)
#define THASH_SECTION_FM (1<<2)
// bit definition of TR, TC search cmobination
//#define THASH_SECTION_TR (1<<0)
//#define THASH_SECTION_TC (1<<1)
/*
* Next bit definition must be same with THASH_TLB_XX
@@ -43,8 +43,7 @@ typedef union search_section {
struct {
u32 tr : 1;
u32 tc : 1;
u32 fm : 1;
u32 rsv: 29;
u32 rsv: 30;
};
u32 v;
} search_section_t;
@@ -80,12 +79,10 @@ typedef struct thash_data {
u64 ig1 : 11; //53-63
};
struct {
u64 __rv1 : 12;
// sizeof(domid_t) must be less than 38!!! Refer to its definition
u64 fm_dom : 38; // 12-49 foreign map domain ID
u64 __rv2 : 3; // 50-52
u64 __rv1 : 53; // 0-52
// next extension to ig1, only for TLB instance
u64 section : 2; // 53-54 TR, TC or FM (thash_TLB_XX)
u64 tc : 1; // 53 TR or TC
u64 locked : 1; // 54 entry locked or not
CACHE_LINE_TYPE cl : 1; // I side or D side cache line
u64 nomap : 1; // entry cann't be inserted into machine TLB.
u64 __ig1 : 5; // 56-61
@@ -227,8 +224,8 @@ typedef struct thash_cb {
INVALID_ENTRY(hcb, hash) = 1; \
hash->next = NULL; }
#define PURGABLE_ENTRY(hcb,en) \
((hcb)->ht == THASH_VHPT || (en)->section == THASH_TLB_TC)
#define PURGABLE_ENTRY(hcb,en) \
((hcb)->ht == THASH_VHPT || ( (en)->tc && !(en->locked)) )
/*
@@ -306,7 +303,7 @@ extern void thash_purge_entries_ex(thash_cb_t *hcb,
u64 rid, u64 va, u64 sz,
search_section_t p_sect,
CACHE_LINE_TYPE cl);
extern thash_cb_t *init_domain_tlb(struct vcpu *d);
extern void thash_purge_and_insert(thash_cb_t *hcb, thash_data_t *in);
/*
* Purge all TCs or VHPT entries including those in Hash table.
@@ -323,6 +320,7 @@ extern thash_data_t *vtlb_lookup(thash_cb_t *hcb,
thash_data_t *in);
extern thash_data_t *vtlb_lookup_ex(thash_cb_t *hcb,
u64 rid, u64 va,CACHE_LINE_TYPE cl);
extern int thash_lock_tc(thash_cb_t *hcb, u64 va, u64 size, int rid, char cl, int lock);
#define ITIR_RV_MASK (((1UL<<32)-1)<<32 | 0x3)
@@ -332,6 +330,7 @@ extern u64 machine_thash(PTA pta, u64 va, u64 rid, u64 ps);
extern void purge_machine_tc_by_domid(domid_t domid);
extern void machine_tlb_insert(struct vcpu *d, thash_data_t *tlb);
extern rr_t vmmu_get_rr(struct vcpu *vcpu, u64 va);
extern thash_cb_t *init_domain_tlb(struct vcpu *d);
#define VTLB_DEBUG
#ifdef VTLB_DEBUG
+1 -1
View File
@@ -25,7 +25,7 @@
struct mmio_list;
typedef struct virutal_platform_def {
//unsigned long *real_mode_data; /* E820, etc. */
//unsigned long shared_page_va;
unsigned long shared_page_va;
//struct vmx_virpit_t vmx_pit;
//struct vmx_handler_t vmx_handler;
//struct mi_per_cpu_info mpci; /* MMIO */
-97
View File
@@ -1,97 +0,0 @@
/*
* Copyright (C) 1998-2003 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
* Stephane Eranian <eranian@hpl.hp.com>
* Copyright (C) 2003 Intel Co
* Suresh Siddha <suresh.b.siddha@intel.com>
* Fenghua Yu <fenghua.yu@intel.com>
* Arun Sharma <arun.sharma@intel.com>
*
* 12/07/98 S. Eranian added pt_regs & switch_stack
* 12/21/98 D. Mosberger updated to match latest code
* 6/17/99 D. Mosberger added second unat member to "struct switch_stack"
* 4/28/05 Anthony Xu ported to Xen
*
*/
struct pt_regs {
/* The following registers are saved by SAVE_MIN: */
unsigned long b6; /* scratch */
unsigned long b7; /* scratch */
unsigned long ar_csd; /* used by cmp8xchg16 (scratch) */
unsigned long ar_ssd; /* reserved for future use (scratch) */
unsigned long r8; /* scratch (return value register 0) */
unsigned long r9; /* scratch (return value register 1) */
unsigned long r10; /* scratch (return value register 2) */
unsigned long r11; /* scratch (return value register 3) */
unsigned long cr_ipsr; /* interrupted task's psr */
unsigned long cr_iip; /* interrupted task's instruction pointer */
unsigned long cr_ifs; /* interrupted task's function state */
unsigned long ar_unat; /* interrupted task's NaT register (preserved) */
unsigned long ar_pfs; /* prev function state */
unsigned long ar_rsc; /* RSE configuration */
/* The following two are valid only if cr_ipsr.cpl > 0: */
unsigned long ar_rnat; /* RSE NaT */
unsigned long ar_bspstore; /* RSE bspstore */
unsigned long pr; /* 64 predicate registers (1 bit each) */
unsigned long b0; /* return pointer (bp) */
unsigned long loadrs; /* size of dirty partition << 16 */
unsigned long r1; /* the gp pointer */
unsigned long r12; /* interrupted task's memory stack pointer */
unsigned long r13; /* thread pointer */
unsigned long ar_fpsr; /* floating point status (preserved) */
unsigned long r15; /* scratch */
/* The remaining registers are NOT saved for system calls. */
unsigned long r14; /* scratch */
unsigned long r2; /* scratch */
unsigned long r3; /* scratch */
unsigned long r4; /* preserved */
unsigned long r5; /* preserved */
unsigned long r6; /* preserved */
unsigned long r7; /* preserved */
unsigned long cr_iipa; /* for emulation */
unsigned long cr_isr; /* for emulation */
unsigned long eml_unat; /* used for emulating instruction */
unsigned long rfi_pfs; /* used for elulating rfi */
/* The following registers are saved by SAVE_REST: */
unsigned long r16; /* scratch */
unsigned long r17; /* scratch */
unsigned long r18; /* scratch */
unsigned long r19; /* scratch */
unsigned long r20; /* scratch */
unsigned long r21; /* scratch */
unsigned long r22; /* scratch */
unsigned long r23; /* scratch */
unsigned long r24; /* scratch */
unsigned long r25; /* scratch */
unsigned long r26; /* scratch */
unsigned long r27; /* scratch */
unsigned long r28; /* scratch */
unsigned long r29; /* scratch */
unsigned long r30; /* scratch */
unsigned long r31; /* scratch */
unsigned long ar_ccv; /* compare/exchange value (scratch) */
/*
* Floating point registers that the kernel considers scratch:
*/
struct ia64_fpreg f6; /* scratch */
struct ia64_fpreg f7; /* scratch */
struct ia64_fpreg f8; /* scratch */
struct ia64_fpreg f9; /* scratch */
struct ia64_fpreg f10; /* scratch */
struct ia64_fpreg f11; /* scratch */
};
+1
View File
@@ -26,6 +26,7 @@
#include <asm/vtm.h>
#include <asm/vmx_platform.h>
#include <public/arch-ia64.h>
#define VPD_SHIFT 17 /* 128K requirement */
#define VPD_SIZE (1 << VPD_SHIFT)
+16
View File
@@ -0,0 +1,16 @@
/******************************************************************************
* event.h
*
* A nice interface for passing asynchronous events to guest OSes.
* (architecture-dependent part)
*
*/
#ifndef __ASM_EVENT_H__
#define __ASM_EVENT_H__
static inline void evtchn_notify(struct vcpu *v)
{
}
#endif
+1
View File
@@ -181,6 +181,7 @@ extern struct cpuinfo_x86 cpu_data[];
#endif
extern int phys_proc_id[NR_CPUS];
extern int cpu_core_id[NR_CPUS];
extern void identify_cpu(struct cpuinfo_x86 *);
extern void print_cpu_info(struct cpuinfo_x86 *);
+2
View File
@@ -8,6 +8,7 @@
#include <xen/config.h>
#include <xen/kernel.h>
#include <xen/cpumask.h>
#include <asm/current.h>
#endif
#ifdef CONFIG_X86_LOCAL_APIC
@@ -34,6 +35,7 @@ extern void smp_alloc_memory(void);
extern int pic_mode;
extern int smp_num_siblings;
extern cpumask_t cpu_sibling_map[];
extern cpumask_t cpu_core_map[];
extern void smp_flush_tlb(void);
extern void smp_invalidate_rcv(void); /* Process an NMI */
+161
View File
@@ -0,0 +1,161 @@
/****************************************************************
* acm.h
*
* Copyright (C) 2005 IBM Corporation
*
* Author:
* Reiner Sailer <sailer@watson.ibm.com>
*
* Contributors:
* Stefan Berger <stefanb@watson.ibm.com>
* added network byte order support for binary policies
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*
* sHype general access control module header file.
* here are all definitions that are shared between
* xen-core, guest-kernels, and applications.
*
* todo: move from static policy choice to compile option.
*/
#ifndef _XEN_PUBLIC_SHYPE_H
#define _XEN_PUBLIC_SHYPE_H
#include "xen.h"
#include "sched_ctl.h"
/* if ACM_DEBUG defined, all hooks should
* print a short trace message (comment it out
* when not in testing mode )
*/
/* #define ACM_DEBUG */
#ifdef ACM_DEBUG
# define printkd(fmt, args...) printk(fmt,## args)
#else
# define printkd(fmt, args...)
#endif
/* default ssid reference value if not supplied */
#define ACM_DEFAULT_SSID 0xffffffff
#define ACM_DEFAULT_LOCAL_SSID 0xffff
/* Internal ACM ERROR types */
#define ACM_OK 0
#define ACM_UNDEF -1
#define ACM_INIT_SSID_ERROR -2
#define ACM_INIT_SOID_ERROR -3
#define ACM_ERROR -4
/* External ACCESS DECISIONS */
#define ACM_ACCESS_PERMITTED 0
#define ACM_ACCESS_DENIED -111
#define ACM_NULL_POINTER_ERROR -200
#define ACM_MAX_POLICY 3
#define ACM_NULL_POLICY 0
#define ACM_CHINESE_WALL_POLICY 1
#define ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY 2
#define ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY 3
/* policy: */
#define ACM_POLICY_NAME(X) \
(X == ACM_NULL_POLICY) ? "NULL policy" : \
(X == ACM_CHINESE_WALL_POLICY) ? "CHINESE WALL policy" : \
(X == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) ? "SIMPLE TYPE ENFORCEMENT policy" : \
(X == ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) ? "CHINESE WALL AND SIMPLE TYPE ENFORCEMENT policy" : \
"UNDEFINED policy"
#ifndef ACM_USE_SECURITY_POLICY
#define ACM_USE_SECURITY_POLICY ACM_NULL_POLICY
#endif
/* defines a ssid reference used by xen */
typedef u32 ssidref_t;
/* -------security policy relevant type definitions-------- */
/* type identifier; compares to "equal" or "not equal" */
typedef u16 domaintype_t;
/* CHINESE WALL POLICY DATA STRUCTURES
*
* current accumulated conflict type set:
* When a domain is started and has a type that is in
* a conflict set, the conflicting types are incremented in
* the aggregate set. When a domain is destroyed, the
* conflicting types to its type are decremented.
* If a domain has multiple types, this procedure works over
* all those types.
*
* conflict_aggregate_set[i] holds the number of
* running domains that have a conflict with type i.
*
* running_types[i] holds the number of running domains
* that include type i in their ssidref-referenced type set
*
* conflict_sets[i][j] is "0" if type j has no conflict
* with type i and is "1" otherwise.
*/
/* high-16 = version, low-16 = check magic */
#define ACM_MAGIC 0x0001debc
/* each offset in bytes from start of the struct they
* the are part of */
/* each buffer consists of all policy information for
* the respective policy given in the policy code
*/
struct acm_policy_buffer {
u32 magic;
u32 policyversion;
u32 len;
u16 primary_policy_code;
u16 primary_buffer_offset;
u16 secondary_policy_code;
u16 secondary_buffer_offset;
};
struct acm_chwall_policy_buffer {
u16 policy_code;
u16 chwall_max_types;
u16 chwall_max_ssidrefs;
u16 chwall_max_conflictsets;
u16 chwall_ssid_offset;
u16 chwall_conflict_sets_offset;
u16 chwall_running_types_offset;
u16 chwall_conflict_aggregate_offset;
};
struct acm_ste_policy_buffer {
u16 policy_code;
u16 ste_max_types;
u16 ste_max_ssidrefs;
u16 ste_ssid_offset;
};
struct acm_stats_buffer {
u32 magic;
u32 policyversion;
u32 len;
u16 primary_policy_code;
u16 primary_stats_offset;
u16 secondary_policy_code;
u16 secondary_stats_offset;
};
struct acm_ste_stats_buffer {
u32 ec_eval_count;
u32 gt_eval_count;
u32 ec_denied_count;
u32 gt_denied_count;
u32 ec_cachehit_count;
u32 gt_cachehit_count;
};
#endif
+34
View File
@@ -0,0 +1,34 @@
/****************************************************************
* acm_dom0_setup.h
*
* Copyright (C) 2005 IBM Corporation
*
* Author:
* Reiner Sailer <sailer@watson.ibm.com>
*
* Includes necessary definitions to bring-up dom0
*/
#include <acm/acm_hooks.h>
extern int acm_init(void);
#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
static inline void acm_post_domain0_create(domid_t domid)
{
return;
}
#else
/* predefined ssidref for DOM0 used by xen when creating DOM0 */
#define ACM_DOM0_SSIDREF 0
static inline void acm_post_domain0_create(domid_t domid)
{
/* initialialize shared sHype security labels for new domain */
acm_init_domain_ssid(domid, ACM_DOM0_SSIDREF);
acm_post_domain_create(domid, ACM_DOM0_SSIDREF);
}
#endif
+129 -9
View File
@@ -14,11 +14,41 @@
#define _MEMORY_PADDING(_X)
#define MEMORY_PADDING
/* Maximum number of virtual CPUs in multi-processor guests. */
/* WARNING: before changing this, check that shared_info fits on a page */
#define MAX_VIRT_CPUS 1
#ifndef __ASSEMBLY__
/* NB. Both the following are 64 bits each. */
typedef unsigned long memory_t; /* Full-sized pointer/address/memory-size. */
#define MAX_NR_SECTION 32 // at most 32 memory holes
typedef struct {
unsigned long start; /* start of memory hole */
unsigned long end; /* end of memory hole */
} mm_section_t;
typedef struct {
unsigned long mfn : 56;
unsigned long type: 8;
} pmt_entry_t;
#define GPFN_MEM (0UL << 56) /* Guest pfn is normal mem */
#define GPFN_FRAME_BUFFER (1UL << 56) /* VGA framebuffer */
#define GPFN_LOW_MMIO (2UL << 56) /* Low MMIO range */
#define GPFN_PIB (3UL << 56) /* PIB base */
#define GPFN_IOSAPIC (4UL << 56) /* IOSAPIC base */
#define GPFN_LEGACY_IO (5UL << 56) /* Legacy I/O base */
#define GPFN_GFW (6UL << 56) /* Guest Firmware */
#define GPFN_HIGH_MMIO (7UL << 56) /* High MMIO range */
#define GPFN_IO_MASK (7UL << 56) /* Guest pfn is I/O type */
#define GPFN_INV_MASK (31UL << 59) /* Guest pfn is invalid */
#define INVALID_MFN (~0UL)
typedef struct
{
} PACKED cpu_user_regs;
@@ -28,11 +58,99 @@ typedef struct
* structure size will still be 8 bytes, so no other alignments will change.
*/
typedef struct {
u32 tsc_bits; /* 0: 32 bits read from the CPU's TSC. */
u32 tsc_bitshift; /* 4: 'tsc_bits' uses N:N+31 of TSC. */
unsigned int tsc_bits; /* 0: 32 bits read from the CPU's TSC. */
unsigned int tsc_bitshift; /* 4: 'tsc_bits' uses N:N+31 of TSC. */
} PACKED tsc_timestamp_t; /* 8 bytes */
#include <asm/tlb.h> /* TR_ENTRY */
struct pt_fpreg {
union {
unsigned long bits[2];
long double __dummy; /* force 16-byte alignment */
} u;
};
struct pt_regs {
/* The following registers are saved by SAVE_MIN: */
unsigned long b6; /* scratch */
unsigned long b7; /* scratch */
unsigned long ar_csd; /* used by cmp8xchg16 (scratch) */
unsigned long ar_ssd; /* reserved for future use (scratch) */
unsigned long r8; /* scratch (return value register 0) */
unsigned long r9; /* scratch (return value register 1) */
unsigned long r10; /* scratch (return value register 2) */
unsigned long r11; /* scratch (return value register 3) */
unsigned long cr_ipsr; /* interrupted task's psr */
unsigned long cr_iip; /* interrupted task's instruction pointer */
unsigned long cr_ifs; /* interrupted task's function state */
unsigned long ar_unat; /* interrupted task's NaT register (preserved) */
unsigned long ar_pfs; /* prev function state */
unsigned long ar_rsc; /* RSE configuration */
/* The following two are valid only if cr_ipsr.cpl > 0: */
unsigned long ar_rnat; /* RSE NaT */
unsigned long ar_bspstore; /* RSE bspstore */
unsigned long pr; /* 64 predicate registers (1 bit each) */
unsigned long b0; /* return pointer (bp) */
unsigned long loadrs; /* size of dirty partition << 16 */
unsigned long r1; /* the gp pointer */
unsigned long r12; /* interrupted task's memory stack pointer */
unsigned long r13; /* thread pointer */
unsigned long ar_fpsr; /* floating point status (preserved) */
unsigned long r15; /* scratch */
/* The remaining registers are NOT saved for system calls. */
unsigned long r14; /* scratch */
unsigned long r2; /* scratch */
unsigned long r3; /* scratch */
#ifdef CONFIG_VTI
unsigned long r4; /* preserved */
unsigned long r5; /* preserved */
unsigned long r6; /* preserved */
unsigned long r7; /* preserved */
unsigned long cr_iipa; /* for emulation */
unsigned long cr_isr; /* for emulation */
unsigned long eml_unat; /* used for emulating instruction */
unsigned long rfi_pfs; /* used for elulating rfi */
#endif
/* The following registers are saved by SAVE_REST: */
unsigned long r16; /* scratch */
unsigned long r17; /* scratch */
unsigned long r18; /* scratch */
unsigned long r19; /* scratch */
unsigned long r20; /* scratch */
unsigned long r21; /* scratch */
unsigned long r22; /* scratch */
unsigned long r23; /* scratch */
unsigned long r24; /* scratch */
unsigned long r25; /* scratch */
unsigned long r26; /* scratch */
unsigned long r27; /* scratch */
unsigned long r28; /* scratch */
unsigned long r29; /* scratch */
unsigned long r30; /* scratch */
unsigned long r31; /* scratch */
unsigned long ar_ccv; /* compare/exchange value (scratch) */
/*
* Floating point registers that the kernel considers scratch:
*/
struct pt_fpreg f6; /* scratch */
struct pt_fpreg f7; /* scratch */
struct pt_fpreg f8; /* scratch */
struct pt_fpreg f9; /* scratch */
struct pt_fpreg f10; /* scratch */
struct pt_fpreg f11; /* scratch */
};
typedef struct {
unsigned long ipsr;
@@ -64,18 +182,20 @@ typedef struct {
unsigned long krs[8]; // kernel registers
unsigned long pkrs[8]; // protection key registers
unsigned long tmp[8]; // temp registers (e.g. for hyperprivops)
//} PACKED arch_shared_info_t;
//} PACKED arch_vcpu_info_t;
} arch_vcpu_info_t; // DON'T PACK
typedef struct {
int evtchn_vector;
int domain_controller_evtchn;
unsigned int flags;
//} PACKED arch_shared_info_t;
} arch_shared_info_t; // DON'T PACK
/*
* The following is all CPU context. Note that the i387_ctxt block is filled
* in by FXSAVE if the CPU has feature FXSR; otherwise FSAVE is used.
*/
typedef struct vcpu_guest_context {
//unsigned long flags;
struct pt_regs regs;
arch_vcpu_info_t vcpu;
arch_shared_info_t shared;
} PACKED vcpu_guest_context_t;
#endif /* !__ASSEMBLY__ */
+3
View File
@@ -73,6 +73,9 @@
#define machine_to_phys_mapping ((u32 *)HYPERVISOR_VIRT_START)
#endif
/* Maximum number of virtual CPUs in multi-processor guests. */
#define MAX_VIRT_CPUS 32
#ifndef __ASSEMBLY__
/* NB. Both the following are 32 bits each. */
+3
View File
@@ -73,6 +73,9 @@
#define HYPERVISOR_VIRT_END (0xFFFF880000000000UL)
#endif
/* Maximum number of virtual CPUs in multi-processor guests. */
#define MAX_VIRT_CPUS 32
#ifndef __ASSEMBLY__
/* The machine->physical mapping table starts at this address, read-only. */
+3
View File
@@ -43,6 +43,8 @@ typedef struct sched_adjdom_cmd dom0_adjustdom_t;
#define DOM0_CREATEDOMAIN 8
typedef struct {
/* IN parameters */
u32 ssidref;
/* IN/OUT parameters. */
/* Identifier for new domain (auto-allocate if zero is specified). */
domid_t domain;
@@ -88,6 +90,7 @@ typedef struct {
u32 n_vcpu;
s32 vcpu_to_cpu[MAX_VIRT_CPUS]; /* current mapping */
cpumap_t cpumap[MAX_VIRT_CPUS]; /* allowable mapping */
u32 ssidref;
} dom0_getdomaininfo_t;
#define DOM0_SETDOMAININFO 13
Loaded 100 of 107 files, more files were not shown because too many files have changed in this diff. Show more
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.