ia64/xen-unstable

view xen/acm/acm_core.c @ 5860:d63b100b327a

Fix restart/poweroff properly. From aq.
author kaf24@firebug.cl.cam.ac.uk
date Tue Jul 26 10:09:06 2005 +0000 (2005-07-26)
parents ecb17ef5a587
children b53a65034532 1efe6f4163ee d18f732c0a5f 361d31028129
line source
1 /****************************************************************
2 * acm_core.c
3 *
4 * Copyright (C) 2005 IBM Corporation
5 *
6 * Author:
7 * Reiner Sailer <sailer@watson.ibm.com>
8 *
9 * Contributors:
10 * Stefan Berger <stefanb@watson.ibm.com>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation, version 2 of the
15 * License.
16 *
17 * sHype access control module (ACM)
18 * This file handles initialization of the ACM
19 * as well as initializing/freeing security
20 * identifiers for domains (it calls on active
21 * policy hook functions).
22 *
23 */
25 #include <xen/config.h>
26 #include <xen/errno.h>
27 #include <xen/types.h>
28 #include <xen/lib.h>
29 #include <xen/delay.h>
30 #include <xen/sched.h>
31 #include <xen/multiboot.h>
32 #include <acm/acm_hooks.h>
33 #include <acm/acm_endian.h>
35 /* debug:
36 * include/acm/acm_hooks.h defines a constant ACM_TRACE_MODE;
37 * define/undefine this constant to receive / suppress any
38 * security hook debug output of sHype
39 *
40 * include/public/acm.h defines a constant ACM_DEBUG
41 * define/undefine this constant to receive non-hook-related
42 * debug output.
43 */
45 /* function prototypes */
46 void acm_init_chwall_policy(void);
47 void acm_init_ste_policy(void);
49 extern struct acm_operations acm_chinesewall_ops,
50 acm_simple_type_enforcement_ops, acm_null_ops;
52 /* global ops structs called by the hooks */
53 struct acm_operations *acm_primary_ops = NULL;
54 /* called in hook if-and-only-if primary succeeds */
55 struct acm_operations *acm_secondary_ops = NULL;
57 /* acm global binary policy (points to 'local' primary and secondary policies */
58 struct acm_binary_policy acm_bin_pol;
59 /* acm binary policy lock */
60 rwlock_t acm_bin_pol_rwlock = RW_LOCK_UNLOCKED;
62 /* until we have endian support in Xen, we discover it at runtime */
63 u8 little_endian = 1;
64 void acm_set_endian(void)
65 {
66 u32 test = 1;
67 if (*((u8 *)&test) == 1) {
68 printk("ACM module running in LITTLE ENDIAN.\n");
69 little_endian = 1;
70 } else {
71 printk("ACM module running in BIG ENDIAN.\n");
72 little_endian = 0;
73 }
74 }
76 #if (ACM_USE_SECURITY_POLICY != ACM_NULL_POLICY)
78 /* initialize global security policy for Xen; policy write-locked already */
79 static void
80 acm_init_binary_policy(void *primary, void *secondary)
81 {
82 acm_bin_pol.primary_policy_code = 0;
83 acm_bin_pol.secondary_policy_code = 0;
84 acm_bin_pol.primary_binary_policy = primary;
85 acm_bin_pol.secondary_binary_policy = secondary;
86 }
88 static int
89 acm_setup(unsigned int *initrdidx,
90 const multiboot_info_t *mbi,
91 unsigned long initial_images_start)
92 {
93 int i;
94 module_t *mod = (module_t *)__va(mbi->mods_addr);
95 int rc = ACM_OK;
97 if (mbi->mods_count > 1)
98 *initrdidx = 1;
100 /*
101 * Try all modules and see whichever could be the binary policy.
102 * Adjust the initrdidx if module[1] is the binary policy.
103 */
104 for (i = mbi->mods_count-1; i >= 1; i--) {
105 struct acm_policy_buffer *pol;
106 char *_policy_start;
107 unsigned long _policy_len;
108 #if defined(__i386__)
109 _policy_start = (char *)(initial_images_start + (mod[i].mod_start-mod[0].mod_start));
110 #elif defined(__x86_64__)
111 _policy_start = __va(initial_images_start + (mod[i].mod_start-mod[0].mod_start));
112 #else
113 #error Architecture unsupported by sHype
114 #endif
115 _policy_len = mod[i].mod_end - mod[i].mod_start;
116 if (_policy_len < sizeof(struct acm_policy_buffer))
117 continue; /* not a policy */
119 pol = (struct acm_policy_buffer *)_policy_start;
120 if (ntohl(pol->magic) == ACM_MAGIC) {
121 rc = acm_set_policy((void *)_policy_start,
122 (u16)_policy_len,
123 ACM_USE_SECURITY_POLICY,
124 0);
125 if (rc == ACM_OK) {
126 printf("Policy len 0x%lx, start at %p.\n",_policy_len,_policy_start);
127 if (i == 1) {
128 if (mbi->mods_count > 2) {
129 *initrdidx = 2;
130 } else {
131 *initrdidx = 0;
132 }
133 } else {
134 *initrdidx = 1;
135 }
136 break;
137 } else {
138 printk("Invalid policy. %d.th module line.\n", i+1);
139 }
140 } /* end if a binary policy definition, i.e., (ntohl(pol->magic) == ACM_MAGIC ) */
141 }
142 return rc;
143 }
146 int
147 acm_init(unsigned int *initrdidx,
148 const multiboot_info_t *mbi,
149 unsigned long initial_images_start)
150 {
151 int ret = -EINVAL;
153 acm_set_endian();
154 write_lock(&acm_bin_pol_rwlock);
156 if (ACM_USE_SECURITY_POLICY == ACM_CHINESE_WALL_POLICY) {
157 acm_init_binary_policy(NULL, NULL);
158 acm_init_chwall_policy();
159 acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
160 acm_primary_ops = &acm_chinesewall_ops;
161 acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
162 acm_secondary_ops = &acm_null_ops;
163 ret = ACM_OK;
164 } else if (ACM_USE_SECURITY_POLICY == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
165 acm_init_binary_policy(NULL, NULL);
166 acm_init_ste_policy();
167 acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
168 acm_primary_ops = &acm_simple_type_enforcement_ops;
169 acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
170 acm_secondary_ops = &acm_null_ops;
171 ret = ACM_OK;
172 } else if (ACM_USE_SECURITY_POLICY == ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
173 acm_init_binary_policy(NULL, NULL);
174 acm_init_chwall_policy();
175 acm_init_ste_policy();
176 acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
177 acm_primary_ops = &acm_chinesewall_ops;
178 acm_bin_pol.secondary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
179 acm_secondary_ops = &acm_simple_type_enforcement_ops;
180 ret = ACM_OK;
181 } else if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) {
182 acm_init_binary_policy(NULL, NULL);
183 acm_bin_pol.primary_policy_code = ACM_NULL_POLICY;
184 acm_primary_ops = &acm_null_ops;
185 acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
186 acm_secondary_ops = &acm_null_ops;
187 ret = ACM_OK;
188 }
189 write_unlock(&acm_bin_pol_rwlock);
191 if (ret != ACM_OK)
192 return -EINVAL;
193 acm_setup(initrdidx, mbi, initial_images_start);
194 printk("%s: Enforcing Primary %s, Secondary %s.\n", __func__,
195 ACM_POLICY_NAME(acm_bin_pol.primary_policy_code), ACM_POLICY_NAME(acm_bin_pol.secondary_policy_code));
196 return ret;
197 }
200 #endif
202 int
203 acm_init_domain_ssid(domid_t id, ssidref_t ssidref)
204 {
205 struct acm_ssid_domain *ssid;
206 struct domain *subj = find_domain_by_id(id);
207 int ret1, ret2;
209 if (subj == NULL) {
210 printk("%s: ACM_NULL_POINTER ERROR (id=%x).\n", __func__, id);
211 return ACM_NULL_POINTER_ERROR;
212 }
213 if ((ssid = xmalloc(struct acm_ssid_domain)) == NULL)
214 return ACM_INIT_SSID_ERROR;
216 ssid->datatype = DOMAIN;
217 ssid->subject = subj;
218 ssid->domainid = subj->domain_id;
219 ssid->primary_ssid = NULL;
220 ssid->secondary_ssid = NULL;
222 if (ACM_USE_SECURITY_POLICY != ACM_NULL_POLICY)
223 ssid->ssidref = ssidref;
224 else
225 ssid->ssidref = ACM_DEFAULT_SSID;
227 subj->ssid = ssid;
228 /* now fill in primary and secondary parts; we only get here through hooks */
229 if (acm_primary_ops->init_domain_ssid != NULL)
230 ret1 = acm_primary_ops->init_domain_ssid(&(ssid->primary_ssid), ssidref);
231 else
232 ret1 = ACM_OK;
234 if (acm_secondary_ops->init_domain_ssid != NULL)
235 ret2 = acm_secondary_ops->init_domain_ssid(&(ssid->secondary_ssid), ssidref);
236 else
237 ret2 = ACM_OK;
239 if ((ret1 != ACM_OK) || (ret2 != ACM_OK)) {
240 printk("%s: ERROR instantiating individual ssids for domain 0x%02x.\n",
241 __func__, subj->domain_id);
242 acm_free_domain_ssid(ssid);
243 put_domain(subj);
244 return ACM_INIT_SSID_ERROR;
245 }
246 printk("%s: assigned domain %x the ssidref=%x.\n", __func__, id, ssid->ssidref);
247 put_domain(subj);
248 return ACM_OK;
249 }
252 int
253 acm_free_domain_ssid(struct acm_ssid_domain *ssid)
254 {
255 domid_t id;
257 /* domain is already gone, just ssid is left */
258 if (ssid == NULL) {
259 printk("%s: ACM_NULL_POINTER ERROR.\n", __func__);
260 return ACM_NULL_POINTER_ERROR;
261 }
262 id = ssid->domainid;
263 ssid->subject = NULL;
265 if (acm_primary_ops->free_domain_ssid != NULL) /* null policy */
266 acm_primary_ops->free_domain_ssid(ssid->primary_ssid);
267 ssid->primary_ssid = NULL;
268 if (acm_secondary_ops->free_domain_ssid != NULL)
269 acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid);
270 ssid->secondary_ssid = NULL;
271 xfree(ssid);
272 printkd("%s: Freed individual domain ssid (domain=%02x).\n",__func__, id);
273 return ACM_OK;
274 }