ia64/xen-unstable

view xen/acm/acm_policy.c @ 10411:4f0bc5744557

[LINUX] Network buffers do not need to be multi-page contiguous
for unprivileged domains (in any case, can fall back to swiotlb).
On non-privileged domain of Xen/IA64, this caused some trouble.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author kaf24@firebug.cl.cam.ac.uk
date Thu Jun 15 13:19:04 2006 +0100 (2006-06-15)
parents 96b1479305ce
children 21e6625a6c01
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 <acm/acm_core.h>
30 #include <public/acm_ops.h>
31 #include <acm/acm_hooks.h>
32 #include <acm/acm_endian.h>
34 int
35 acm_set_policy(XEN_GUEST_HANDLE(void) buf, u32 buf_size, int isuserbuffer)
36 {
37 u8 *policy_buffer = NULL;
38 struct acm_policy_buffer *pol;
40 if (buf_size < sizeof(struct acm_policy_buffer))
41 return -EFAULT;
43 /* 1. copy buffer from domain */
44 if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL)
45 return -ENOMEM;
47 if (isuserbuffer) {
48 if (copy_from_guest(policy_buffer, buf, buf_size))
49 {
50 printk("%s: Error copying!\n",__func__);
51 goto error_free;
52 }
53 } else
54 memcpy(policy_buffer, buf, buf_size);
56 /* 2. some sanity checking */
57 pol = (struct acm_policy_buffer *)policy_buffer;
59 if ((ntohl(pol->magic) != ACM_MAGIC) ||
60 (buf_size != ntohl(pol->len)) ||
61 (ntohl(pol->policy_version) != ACM_POLICY_VERSION))
62 {
63 printk("%s: ERROR in Magic, Version, or buf size.\n", __func__);
64 goto error_free;
65 }
67 if (acm_active_security_policy == ACM_POLICY_UNDEFINED) {
68 /* setup the policy with the boot policy */
69 if (acm_init_binary_policy((ntohl(pol->secondary_policy_code) << 4) |
70 ntohl(pol->primary_policy_code))) {
71 goto error_free;
72 }
73 acm_active_security_policy =
74 (acm_bin_pol.secondary_policy_code << 4) | acm_bin_pol.primary_policy_code;
75 }
77 /* once acm_active_security_policy is set, it cannot be changed */
78 if ((ntohl(pol->primary_policy_code) != acm_bin_pol.primary_policy_code) ||
79 (ntohl(pol->secondary_policy_code) != acm_bin_pol.secondary_policy_code))
80 {
81 printkd("%s: Wrong policy type in boot policy!\n", __func__);
82 goto error_free;
83 }
85 /* get bin_policy lock and rewrite policy (release old one) */
86 write_lock(&acm_bin_pol_rwlock);
88 /* 3. set label reference name */
89 if (acm_set_policy_reference(buf + ntohl(pol->policy_reference_offset),
90 ntohl(pol->primary_buffer_offset) -
91 ntohl(pol->policy_reference_offset)))
92 goto error_lock_free;
94 /* 4. set primary policy data */
95 if (acm_primary_ops->set_binary_policy(buf + ntohl(pol->primary_buffer_offset),
96 ntohl(pol->secondary_buffer_offset) -
97 ntohl(pol->primary_buffer_offset)))
98 goto error_lock_free;
100 /* 5. set secondary policy data */
101 if (acm_secondary_ops->set_binary_policy(buf + ntohl(pol->secondary_buffer_offset),
102 ntohl(pol->len) -
103 ntohl(pol->secondary_buffer_offset)))
104 goto error_lock_free;
106 write_unlock(&acm_bin_pol_rwlock);
107 xfree(policy_buffer);
108 return ACM_OK;
110 error_lock_free:
111 write_unlock(&acm_bin_pol_rwlock);
112 error_free:
113 printk("%s: Error setting policy.\n", __func__);
114 xfree(policy_buffer);
115 return -EFAULT;
116 }
118 int
119 acm_get_policy(XEN_GUEST_HANDLE(void) buf, u32 buf_size)
120 {
121 u8 *policy_buffer;
122 int ret;
123 struct acm_policy_buffer *bin_pol;
125 if (buf_size < sizeof(struct acm_policy_buffer))
126 return -EFAULT;
128 if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL)
129 return -ENOMEM;
131 read_lock(&acm_bin_pol_rwlock);
133 bin_pol = (struct acm_policy_buffer *)policy_buffer;
134 bin_pol->magic = htonl(ACM_MAGIC);
135 bin_pol->primary_policy_code = htonl(acm_bin_pol.primary_policy_code);
136 bin_pol->secondary_policy_code = htonl(acm_bin_pol.secondary_policy_code);
138 bin_pol->len = htonl(sizeof(struct acm_policy_buffer));
139 bin_pol->policy_reference_offset = htonl(ntohl(bin_pol->len));
140 bin_pol->primary_buffer_offset = htonl(ntohl(bin_pol->len));
141 bin_pol->secondary_buffer_offset = htonl(ntohl(bin_pol->len));
143 ret = acm_dump_policy_reference(policy_buffer + ntohl(bin_pol->policy_reference_offset),
144 buf_size - ntohl(bin_pol->policy_reference_offset));
145 if (ret < 0)
146 goto error_free_unlock;
148 bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
149 bin_pol->primary_buffer_offset = htonl(ntohl(bin_pol->len));
151 ret = acm_primary_ops->dump_binary_policy (policy_buffer + ntohl(bin_pol->primary_buffer_offset),
152 buf_size - ntohl(bin_pol->primary_buffer_offset));
153 if (ret < 0)
154 goto error_free_unlock;
156 bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
157 bin_pol->secondary_buffer_offset = htonl(ntohl(bin_pol->len));
159 ret = acm_secondary_ops->dump_binary_policy(policy_buffer + ntohl(bin_pol->secondary_buffer_offset),
160 buf_size - ntohl(bin_pol->secondary_buffer_offset));
161 if (ret < 0)
162 goto error_free_unlock;
164 bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
165 if (copy_to_guest(buf, policy_buffer, ntohl(bin_pol->len)))
166 goto error_free_unlock;
168 read_unlock(&acm_bin_pol_rwlock);
169 xfree(policy_buffer);
170 return ACM_OK;
172 error_free_unlock:
173 read_unlock(&acm_bin_pol_rwlock);
174 printk("%s: Error getting policy.\n", __func__);
175 xfree(policy_buffer);
176 return -EFAULT;
177 }
179 int
180 acm_dump_statistics(XEN_GUEST_HANDLE(void) buf, u16 buf_size)
181 {
182 /* send stats to user space */
183 u8 *stats_buffer;
184 int len1, len2;
185 struct acm_stats_buffer acm_stats;
187 if ((stats_buffer = xmalloc_array(u8, buf_size)) == NULL)
188 return -ENOMEM;
190 read_lock(&acm_bin_pol_rwlock);
192 len1 = acm_primary_ops->dump_statistics(stats_buffer + sizeof(struct acm_stats_buffer),
193 buf_size - sizeof(struct acm_stats_buffer));
194 if (len1 < 0)
195 goto error_lock_free;
197 len2 = acm_secondary_ops->dump_statistics(stats_buffer + sizeof(struct acm_stats_buffer) + len1,
198 buf_size - sizeof(struct acm_stats_buffer) - len1);
199 if (len2 < 0)
200 goto error_lock_free;
202 acm_stats.magic = htonl(ACM_MAGIC);
203 acm_stats.primary_policy_code = htonl(acm_bin_pol.primary_policy_code);
204 acm_stats.secondary_policy_code = htonl(acm_bin_pol.secondary_policy_code);
205 acm_stats.primary_stats_offset = htonl(sizeof(struct acm_stats_buffer));
206 acm_stats.secondary_stats_offset = htonl(sizeof(struct acm_stats_buffer) + len1);
207 acm_stats.len = htonl(sizeof(struct acm_stats_buffer) + len1 + len2);
209 memcpy(stats_buffer, &acm_stats, sizeof(struct acm_stats_buffer));
211 if (copy_to_guest(buf, stats_buffer, sizeof(struct acm_stats_buffer) + len1 + len2))
212 goto error_lock_free;
214 read_unlock(&acm_bin_pol_rwlock);
215 xfree(stats_buffer);
216 return ACM_OK;
218 error_lock_free:
219 read_unlock(&acm_bin_pol_rwlock);
220 xfree(stats_buffer);
221 return -EFAULT;
222 }
225 int
226 acm_get_ssid(ssidref_t ssidref, XEN_GUEST_HANDLE(void) buf, u16 buf_size)
227 {
228 /* send stats to user space */
229 u8 *ssid_buffer;
230 int ret;
231 struct acm_ssid_buffer *acm_ssid;
232 if (buf_size < sizeof(struct acm_ssid_buffer))
233 return -EFAULT;
235 if ((ssid_buffer = xmalloc_array(u8, buf_size)) == NULL)
236 return -ENOMEM;
238 read_lock(&acm_bin_pol_rwlock);
240 acm_ssid = (struct acm_ssid_buffer *)ssid_buffer;
241 acm_ssid->len = sizeof(struct acm_ssid_buffer);
242 acm_ssid->ssidref = ssidref;
243 acm_ssid->primary_policy_code = acm_bin_pol.primary_policy_code;
244 acm_ssid->secondary_policy_code = acm_bin_pol.secondary_policy_code;
246 acm_ssid->policy_reference_offset = acm_ssid->len;
247 ret = acm_dump_policy_reference(ssid_buffer + acm_ssid->policy_reference_offset,
248 buf_size - acm_ssid->policy_reference_offset);
249 if (ret < 0)
250 goto error_free_unlock;
252 acm_ssid->len += ret;
253 acm_ssid->primary_types_offset = acm_ssid->len;
255 /* ret >= 0 --> ret == max_types */
256 ret = acm_primary_ops->dump_ssid_types(ACM_PRIMARY(ssidref),
257 ssid_buffer + acm_ssid->primary_types_offset,
258 buf_size - acm_ssid->primary_types_offset);
259 if (ret < 0)
260 goto error_free_unlock;
262 acm_ssid->len += ret;
263 acm_ssid->primary_max_types = ret;
264 acm_ssid->secondary_types_offset = acm_ssid->len;
266 ret = acm_secondary_ops->dump_ssid_types(ACM_SECONDARY(ssidref),
267 ssid_buffer + acm_ssid->secondary_types_offset,
268 buf_size - acm_ssid->secondary_types_offset);
269 if (ret < 0)
270 goto error_free_unlock;
272 acm_ssid->len += ret;
273 acm_ssid->secondary_max_types = ret;
275 if (copy_to_guest(buf, ssid_buffer, acm_ssid->len))
276 goto error_free_unlock;
278 read_unlock(&acm_bin_pol_rwlock);
279 xfree(ssid_buffer);
280 return ACM_OK;
282 error_free_unlock:
283 read_unlock(&acm_bin_pol_rwlock);
284 printk("%s: Error getting ssid.\n", __func__);
285 xfree(ssid_buffer);
286 return -ENOMEM;
287 }
289 int
290 acm_get_decision(ssidref_t ssidref1, ssidref_t ssidref2, u32 hook)
291 {
292 int ret = ACM_ACCESS_DENIED;
293 switch (hook) {
295 case ACMHOOK_sharing:
296 /* Sharing hook restricts access in STE policy only */
297 ret = acm_sharing(ssidref1, ssidref2);
298 break;
300 default:
301 /* deny */
302 break;
303 }
305 printkd("%s: ssid1=%x, ssid2=%x, decision=%s.\n",
306 __func__, ssidref1, ssidref2,
307 (ret == ACM_ACCESS_PERMITTED) ? "GRANTED" : "DENIED");
309 return ret;
310 }
312 /*
313 * Local variables:
314 * mode: C
315 * c-set-style: "BSD"
316 * c-basic-offset: 4
317 * tab-width: 4
318 * indent-tabs-mode: nil
319 * End:
320 */