ia64/xen-unstable

view xen/acm/acm_policy.c @ 14858:249de074617f

Added documentation, C bindings, and test for VM_metrics.VCPUs_flags.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Fri Apr 13 18:14:06 2007 +0100 (2007-04-13)
parents 4434d1039a65
children 4677ee247aa9
line source
1 /****************************************************************
2 * acm_policy.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 policy management for Xen.
18 * This interface allows policy tools in authorized
19 * domains to interact with the Xen access control module
20 *
21 */
23 #include <xen/config.h>
24 #include <xen/errno.h>
25 #include <xen/types.h>
26 #include <xen/lib.h>
27 #include <xen/delay.h>
28 #include <xen/sched.h>
29 #include <xen/guest_access.h>
30 #include <acm/acm_core.h>
31 #include <public/acm_ops.h>
32 #include <acm/acm_hooks.h>
33 #include <acm/acm_endian.h>
35 int
36 acm_set_policy(XEN_GUEST_HANDLE(void) buf, u32 buf_size)
37 {
38 u8 *policy_buffer = NULL;
39 int ret = -EFAULT;
41 if (buf_size < sizeof(struct acm_policy_buffer))
42 return -EFAULT;
44 /* copy buffer from guest domain */
45 if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL)
46 return -ENOMEM;
48 if (copy_from_guest(policy_buffer, buf, buf_size))
49 {
50 printk("%s: Error copying!\n",__func__);
51 goto error_free;
52 }
53 ret = do_acm_set_policy(policy_buffer, buf_size, 0);
55 error_free:
56 xfree(policy_buffer);
57 return ret;
58 }
61 int
62 do_acm_set_policy(void *buf, u32 buf_size, int is_bootpolicy)
63 {
64 struct acm_policy_buffer *pol = (struct acm_policy_buffer *)buf;
65 uint32_t offset, length;
66 /* some sanity checking */
67 if ((be32_to_cpu(pol->magic) != ACM_MAGIC) ||
68 (buf_size != be32_to_cpu(pol->len)) ||
69 (be32_to_cpu(pol->policy_version) != ACM_POLICY_VERSION))
70 {
71 printk("%s: ERROR in Magic, Version, or buf size.\n", __func__);
72 goto error_free;
73 }
75 if (acm_active_security_policy == ACM_POLICY_UNDEFINED) {
76 /* setup the policy with the boot policy */
77 if (acm_init_binary_policy((be32_to_cpu(pol->secondary_policy_code) << 4) |
78 be32_to_cpu(pol->primary_policy_code))) {
79 goto error_free;
80 }
81 acm_active_security_policy =
82 (acm_bin_pol.secondary_policy_code << 4) | acm_bin_pol.primary_policy_code;
83 }
85 /* once acm_active_security_policy is set, it cannot be changed */
86 if ((be32_to_cpu(pol->primary_policy_code) != acm_bin_pol.primary_policy_code) ||
87 (be32_to_cpu(pol->secondary_policy_code) != acm_bin_pol.secondary_policy_code))
88 {
89 printkd("%s: Wrong policy type in boot policy!\n", __func__);
90 goto error_free;
91 }
93 /* get bin_policy lock and rewrite policy (release old one) */
94 write_lock(&acm_bin_pol_rwlock);
96 offset = be32_to_cpu(pol->policy_reference_offset);
97 length = be32_to_cpu(pol->primary_buffer_offset) - offset;
99 /* set label reference name */
100 if ( (offset + length) > buf_size ||
101 acm_set_policy_reference(buf + offset, length))
102 goto error_lock_free;
104 /* set primary policy data */
105 offset = be32_to_cpu(pol->primary_buffer_offset);
106 length = be32_to_cpu(pol->secondary_buffer_offset) - offset;
108 if ( (offset + length) > buf_size ||
109 acm_primary_ops->set_binary_policy(buf + offset, length,
110 is_bootpolicy))
111 goto error_lock_free;
113 /* set secondary policy data */
114 offset = be32_to_cpu(pol->secondary_buffer_offset);
115 length = be32_to_cpu(pol->len) - offset;
116 if ( (offset + length) > buf_size ||
117 acm_secondary_ops->set_binary_policy(buf + offset, length,
118 is_bootpolicy))
119 goto error_lock_free;
121 memcpy(&acm_bin_pol.xml_pol_version,
122 &pol->xml_pol_version,
123 sizeof(acm_bin_pol.xml_pol_version));
125 write_unlock(&acm_bin_pol_rwlock);
126 return ACM_OK;
128 error_lock_free:
129 write_unlock(&acm_bin_pol_rwlock);
130 error_free:
131 printk("%s: Error setting policy.\n", __func__);
132 return -EFAULT;
133 }
135 int
136 acm_get_policy(XEN_GUEST_HANDLE(void) buf, u32 buf_size)
137 {
138 u8 *policy_buffer;
139 int ret;
140 struct acm_policy_buffer *bin_pol;
142 if (buf_size < sizeof(struct acm_policy_buffer))
143 return -EFAULT;
145 if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL)
146 return -ENOMEM;
148 read_lock(&acm_bin_pol_rwlock);
150 bin_pol = (struct acm_policy_buffer *)policy_buffer;
151 bin_pol->magic = cpu_to_be32(ACM_MAGIC);
152 bin_pol->primary_policy_code = cpu_to_be32(acm_bin_pol.primary_policy_code);
153 bin_pol->secondary_policy_code = cpu_to_be32(acm_bin_pol.secondary_policy_code);
155 bin_pol->len = cpu_to_be32(sizeof(struct acm_policy_buffer));
156 bin_pol->policy_reference_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
157 bin_pol->primary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
158 bin_pol->secondary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
160 memcpy(&bin_pol->xml_pol_version,
161 &acm_bin_pol.xml_pol_version,
162 sizeof(struct acm_policy_version));
164 ret = acm_dump_policy_reference(policy_buffer + be32_to_cpu(bin_pol->policy_reference_offset),
165 buf_size - be32_to_cpu(bin_pol->policy_reference_offset));
166 if (ret < 0)
167 goto error_free_unlock;
169 bin_pol->len = cpu_to_be32(be32_to_cpu(bin_pol->len) + ret);
170 bin_pol->primary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
172 ret = acm_primary_ops->dump_binary_policy (policy_buffer + be32_to_cpu(bin_pol->primary_buffer_offset),
173 buf_size - be32_to_cpu(bin_pol->primary_buffer_offset));
174 if (ret < 0)
175 goto error_free_unlock;
177 bin_pol->len = cpu_to_be32(be32_to_cpu(bin_pol->len) + ret);
178 bin_pol->secondary_buffer_offset = cpu_to_be32(be32_to_cpu(bin_pol->len));
180 ret = acm_secondary_ops->dump_binary_policy(policy_buffer + be32_to_cpu(bin_pol->secondary_buffer_offset),
181 buf_size - be32_to_cpu(bin_pol->secondary_buffer_offset));
182 if (ret < 0)
183 goto error_free_unlock;
185 bin_pol->len = cpu_to_be32(be32_to_cpu(bin_pol->len) + ret);
186 if (copy_to_guest(buf, policy_buffer, be32_to_cpu(bin_pol->len)))
187 goto error_free_unlock;
189 read_unlock(&acm_bin_pol_rwlock);
190 xfree(policy_buffer);
191 return ACM_OK;
193 error_free_unlock:
194 read_unlock(&acm_bin_pol_rwlock);
195 printk("%s: Error getting policy.\n", __func__);
196 xfree(policy_buffer);
197 return -EFAULT;
198 }
200 int
201 acm_dump_statistics(XEN_GUEST_HANDLE(void) buf, u16 buf_size)
202 {
203 /* send stats to user space */
204 u8 *stats_buffer;
205 int len1, len2;
206 struct acm_stats_buffer acm_stats;
208 if ((stats_buffer = xmalloc_array(u8, buf_size)) == NULL)
209 return -ENOMEM;
211 read_lock(&acm_bin_pol_rwlock);
213 len1 = acm_primary_ops->dump_statistics(stats_buffer + sizeof(struct acm_stats_buffer),
214 buf_size - sizeof(struct acm_stats_buffer));
215 if (len1 < 0)
216 goto error_lock_free;
218 len2 = acm_secondary_ops->dump_statistics(stats_buffer + sizeof(struct acm_stats_buffer) + len1,
219 buf_size - sizeof(struct acm_stats_buffer) - len1);
220 if (len2 < 0)
221 goto error_lock_free;
223 acm_stats.magic = cpu_to_be32(ACM_MAGIC);
224 acm_stats.primary_policy_code = cpu_to_be32(acm_bin_pol.primary_policy_code);
225 acm_stats.secondary_policy_code = cpu_to_be32(acm_bin_pol.secondary_policy_code);
226 acm_stats.primary_stats_offset = cpu_to_be32(sizeof(struct acm_stats_buffer));
227 acm_stats.secondary_stats_offset = cpu_to_be32(sizeof(struct acm_stats_buffer) + len1);
228 acm_stats.len = cpu_to_be32(sizeof(struct acm_stats_buffer) + len1 + len2);
230 memcpy(stats_buffer, &acm_stats, sizeof(struct acm_stats_buffer));
232 if (copy_to_guest(buf, stats_buffer, sizeof(struct acm_stats_buffer) + len1 + len2))
233 goto error_lock_free;
235 read_unlock(&acm_bin_pol_rwlock);
236 xfree(stats_buffer);
237 return ACM_OK;
239 error_lock_free:
240 read_unlock(&acm_bin_pol_rwlock);
241 xfree(stats_buffer);
242 return -EFAULT;
243 }
246 int
247 acm_get_ssid(ssidref_t ssidref, XEN_GUEST_HANDLE(void) buf, u16 buf_size)
248 {
249 /* send stats to user space */
250 u8 *ssid_buffer;
251 int ret;
252 struct acm_ssid_buffer *acm_ssid;
253 if (buf_size < sizeof(struct acm_ssid_buffer))
254 return -EFAULT;
256 if ((ssid_buffer = xmalloc_array(u8, buf_size)) == NULL)
257 return -ENOMEM;
259 read_lock(&acm_bin_pol_rwlock);
261 acm_ssid = (struct acm_ssid_buffer *)ssid_buffer;
262 acm_ssid->len = sizeof(struct acm_ssid_buffer);
263 acm_ssid->ssidref = ssidref;
264 acm_ssid->primary_policy_code = acm_bin_pol.primary_policy_code;
265 acm_ssid->secondary_policy_code = acm_bin_pol.secondary_policy_code;
267 acm_ssid->policy_reference_offset = acm_ssid->len;
268 ret = acm_dump_policy_reference(ssid_buffer + acm_ssid->policy_reference_offset,
269 buf_size - acm_ssid->policy_reference_offset);
270 if (ret < 0)
271 goto error_free_unlock;
273 acm_ssid->len += ret;
274 acm_ssid->primary_types_offset = acm_ssid->len;
276 /* ret >= 0 --> ret == max_types */
277 ret = acm_primary_ops->dump_ssid_types(ACM_PRIMARY(ssidref),
278 ssid_buffer + acm_ssid->primary_types_offset,
279 buf_size - acm_ssid->primary_types_offset);
280 if (ret < 0)
281 goto error_free_unlock;
283 acm_ssid->len += ret;
284 acm_ssid->primary_max_types = ret;
285 acm_ssid->secondary_types_offset = acm_ssid->len;
287 ret = acm_secondary_ops->dump_ssid_types(ACM_SECONDARY(ssidref),
288 ssid_buffer + acm_ssid->secondary_types_offset,
289 buf_size - acm_ssid->secondary_types_offset);
290 if (ret < 0)
291 goto error_free_unlock;
293 acm_ssid->len += ret;
294 acm_ssid->secondary_max_types = ret;
296 if (copy_to_guest(buf, ssid_buffer, acm_ssid->len))
297 goto error_free_unlock;
299 read_unlock(&acm_bin_pol_rwlock);
300 xfree(ssid_buffer);
301 return ACM_OK;
303 error_free_unlock:
304 read_unlock(&acm_bin_pol_rwlock);
305 printk("%s: Error getting ssid.\n", __func__);
306 xfree(ssid_buffer);
307 return -ENOMEM;
308 }
310 int
311 acm_get_decision(ssidref_t ssidref1, ssidref_t ssidref2, u32 hook)
312 {
313 int ret = ACM_ACCESS_DENIED;
314 switch (hook) {
316 case ACMHOOK_sharing:
317 /* Sharing hook restricts access in STE policy only */
318 ret = acm_sharing(ssidref1, ssidref2);
319 break;
321 default:
322 /* deny */
323 break;
324 }
326 printkd("%s: ssid1=%x, ssid2=%x, decision=%s.\n",
327 __func__, ssidref1, ssidref2,
328 (ret == ACM_ACCESS_PERMITTED) ? "GRANTED" : "DENIED");
330 return ret;
331 }
333 /*
334 * Local variables:
335 * mode: C
336 * c-set-style: "BSD"
337 * c-basic-offset: 4
338 * tab-width: 4
339 * indent-tabs-mode: nil
340 * End:
341 */