ia64/xen-unstable

view tools/python/xen/lowlevel/acm/acm.c @ 18059:4b882c41c9b9

tools: Make functions static which should not be exported.
Signed-off-by: Christoph Egger <Christoph.Egger@amd.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jul 15 15:03:58 2008 +0100 (2008-07-15)
parents f769baf14332
children f7f8f44b9292
line source
1 /****************************************************************
2 * acm.c
3 *
4 * Copyright (C) 2006,2007 IBM Corporation
5 *
6 * Authors:
7 * Reiner Sailer <sailer@watson.ibm.com>
8 * Stefan Berger <stefanb@us.ibm.com>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation, version 2 of the
13 * License.
14 *
15 * ACM low-level code that allows Python control code to leverage
16 * the ACM hypercall interface to retrieve real-time information
17 * from the Xen hypervisor security module.
18 *
19 * indent -i4 -kr -nut
20 */
22 #include <Python.h>
24 #include <stdio.h>
25 #include <fcntl.h>
26 #include <sys/mman.h>
27 #include <sys/types.h>
28 #include <stdlib.h>
29 #include <arpa/inet.h>
30 #include <sys/ioctl.h>
31 #include <netinet/in.h>
32 #include <xenctrl.h>
33 #include <xen/xsm/acm.h>
34 #include <xen/xsm/acm_ops.h>
36 #define PERROR(_m, _a...) \
37 fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
38 errno, strerror(errno))
40 static PyObject *acm_error_obj;
42 /* generic shared function */
43 static void *__getssid(int domid, uint32_t *buflen)
44 {
45 struct acm_getssid getssid;
46 int xc_handle;
47 #define SSID_BUFFER_SIZE 4096
48 void *buf = NULL;
50 if ((xc_handle = xc_interface_open()) < 0) {
51 goto out1;
52 }
53 if ((buf = malloc(SSID_BUFFER_SIZE)) == NULL) {
54 PERROR("acm.policytype: Could not allocate ssid buffer!\n");
55 goto out2;
56 }
57 memset(buf, 0, SSID_BUFFER_SIZE);
58 set_xen_guest_handle(getssid.ssidbuf, buf);
59 getssid.ssidbuf_size = SSID_BUFFER_SIZE;
60 getssid.get_ssid_by = ACM_GETBY_domainid;
61 getssid.id.domainid = domid;
63 if (xc_acm_op(xc_handle, ACMOP_getssid, &getssid, sizeof(getssid)) < 0) {
64 if (errno == EACCES)
65 PERROR("ACM operation failed.");
66 free(buf);
67 buf = NULL;
68 goto out2;
69 } else {
70 *buflen = SSID_BUFFER_SIZE;
71 goto out2;
72 }
73 out2:
74 xc_interface_close(xc_handle);
75 out1:
76 return buf;
77 }
80 /* retrieve the policytype indirectly by retrieving the
81 * ssidref for domain 0 (always exists) */
82 static PyObject *policy(PyObject * self, PyObject * args)
83 {
84 /* out */
85 char *policyreference;
86 PyObject *ret;
87 void *ssid_buffer;
88 uint32_t buf_len;
90 if (!PyArg_ParseTuple(args, "", NULL)) {
91 return NULL;
92 }
93 ssid_buffer = __getssid(0, &buf_len);
94 if (ssid_buffer == NULL || buf_len < sizeof(struct acm_ssid_buffer)) {
95 free(ssid_buffer);
96 return PyErr_SetFromErrno(acm_error_obj);
97 }
98 else {
99 struct acm_ssid_buffer *ssid = (struct acm_ssid_buffer *)ssid_buffer;
100 policyreference = (char *)(ssid_buffer + ssid->policy_reference_offset
101 + sizeof (struct acm_policy_reference_buffer));
102 ret = Py_BuildValue("s", policyreference);
103 free(ssid_buffer);
104 return ret;
105 }
106 }
109 /* retrieve ssid info for a domain domid*/
110 static PyObject *getssid(PyObject * self, PyObject * args)
111 {
112 /* in */
113 uint32_t domid;
114 /* out */
115 char *policytype, *policyreference;
116 uint32_t ssidref;
118 void *ssid_buffer;
119 uint32_t buf_len;
121 if (!PyArg_ParseTuple(args, "i", &domid)) {
122 return NULL;
123 }
124 ssid_buffer = __getssid(domid, &buf_len);
125 if (ssid_buffer == NULL) {
126 return NULL;
127 } else if (buf_len < sizeof(struct acm_ssid_buffer)) {
128 free(ssid_buffer);
129 return NULL;
130 } else {
131 struct acm_ssid_buffer *ssid = (struct acm_ssid_buffer *) ssid_buffer;
132 policytype = ACM_POLICY_NAME(ssid->secondary_policy_code << 4 |
133 ssid->primary_policy_code);
134 ssidref = ssid->ssidref;
135 policyreference = (char *)(ssid_buffer + ssid->policy_reference_offset
136 + sizeof (struct acm_policy_reference_buffer));
137 }
138 free(ssid_buffer);
139 return Py_BuildValue("{s:s,s:s,s:i}",
140 "policyreference", policyreference,
141 "policytype", policytype,
142 "ssidref", ssidref);
143 }
146 /* retrieve access decision based on domain ids or ssidrefs */
147 static PyObject *getdecision(PyObject * self, PyObject * args)
148 {
149 char *arg1_name, *arg1, *arg2_name, *arg2, *decision = NULL;
150 struct acm_getdecision getdecision;
151 int xc_handle, rc;
152 uint32_t hooktype;
154 if (!PyArg_ParseTuple(args, "ssssi", &arg1_name,
155 &arg1, &arg2_name, &arg2, &hooktype)) {
156 return NULL;
157 }
159 if ((xc_handle = xc_interface_open()) <= 0) {
160 PERROR("Could not open xen privcmd device!\n");
161 return NULL;
162 }
164 if ((strcmp(arg1_name, "domid") && strcmp(arg1_name, "ssidref")) ||
165 (strcmp(arg2_name, "domid") && strcmp(arg2_name, "ssidref")))
166 return NULL;
168 getdecision.hook = hooktype;
169 if (!strcmp(arg1_name, "domid")) {
170 getdecision.get_decision_by1 = ACM_GETBY_domainid;
171 getdecision.id1.domainid = atoi(arg1);
172 } else {
173 getdecision.get_decision_by1 = ACM_GETBY_ssidref;
174 getdecision.id1.ssidref = atol(arg1);
175 }
176 if (!strcmp(arg2_name, "domid")) {
177 getdecision.get_decision_by2 = ACM_GETBY_domainid;
178 getdecision.id2.domainid = atoi(arg2);
179 } else {
180 getdecision.get_decision_by2 = ACM_GETBY_ssidref;
181 getdecision.id2.ssidref = atol(arg2);
182 }
184 rc = xc_acm_op(xc_handle, ACMOP_getdecision,
185 &getdecision, sizeof(getdecision));
187 xc_interface_close(xc_handle);
189 if (rc < 0) {
190 if (errno == EACCES)
191 PERROR("ACM operation failed.");
192 return NULL;
193 }
195 if (getdecision.acm_decision == ACM_ACCESS_PERMITTED)
196 decision = "PERMITTED";
197 else if (getdecision.acm_decision == ACM_ACCESS_DENIED)
198 decision = "DENIED";
200 return Py_BuildValue("s", decision);
201 }
203 /* error messages for exceptions */
204 const char bad_arg[] = "Bad function argument.";
205 const char ctrlif_op[] = "Could not open control interface.";
206 const char hv_op_err[] = "Error from hypervisor operation.";
209 static PyObject *chgpolicy(PyObject *self, PyObject *args)
210 {
211 struct acm_change_policy chgpolicy;
212 int xc_handle, rc;
213 char *bin_pol = NULL, *del_arr = NULL, *chg_arr = NULL;
214 int bin_pol_len = 0, del_arr_len = 0, chg_arr_len = 0;
215 uint errarray_mbrs = 20 * 2;
216 uint32_t error_array[errarray_mbrs];
217 PyObject *result;
218 uint len;
220 memset(&chgpolicy, 0x0, sizeof(chgpolicy));
222 if (!PyArg_ParseTuple(args, "s#s#s#" ,&bin_pol, &bin_pol_len,
223 &del_arr, &del_arr_len,
224 &chg_arr, &chg_arr_len)) {
225 PyErr_SetString(PyExc_TypeError, bad_arg);
226 return NULL;
227 }
229 chgpolicy.policy_pushcache_size = bin_pol_len;
230 chgpolicy.delarray_size = del_arr_len;
231 chgpolicy.chgarray_size = chg_arr_len;
232 chgpolicy.errarray_size = sizeof(error_array);
234 set_xen_guest_handle(chgpolicy.policy_pushcache, bin_pol);
235 set_xen_guest_handle(chgpolicy.del_array, del_arr);
236 set_xen_guest_handle(chgpolicy.chg_array, chg_arr);
237 set_xen_guest_handle(chgpolicy.err_array, error_array);
239 if ((xc_handle = xc_interface_open()) <= 0) {
240 PyErr_SetString(PyExc_IOError, ctrlif_op);
241 return NULL;
242 }
244 rc = xc_acm_op(xc_handle, ACMOP_chgpolicy, &chgpolicy, sizeof(chgpolicy));
246 xc_interface_close(xc_handle);
248 /* only pass the filled error codes */
249 for (len = 0; (len + 1) < errarray_mbrs; len += 2) {
250 if (error_array[len] == 0) {
251 len *= sizeof(error_array[0]);
252 break;
253 }
254 }
256 result = Py_BuildValue("is#", rc, error_array, len);
257 return result;
258 }
261 static PyObject *getpolicy(PyObject *self, PyObject *args)
262 {
263 struct acm_getpolicy getpolicy;
264 int xc_handle, rc;
265 uint8_t pull_buffer[8192];
266 PyObject *result;
267 uint32_t len = sizeof(pull_buffer);
269 memset(&getpolicy, 0x0, sizeof(getpolicy));
270 set_xen_guest_handle(getpolicy.pullcache, pull_buffer);
271 getpolicy.pullcache_size = sizeof(pull_buffer);
273 if ((xc_handle = xc_interface_open()) <= 0) {
274 PyErr_SetString(PyExc_IOError, ctrlif_op);
275 return NULL;
276 }
278 rc = xc_acm_op(xc_handle, ACMOP_getpolicy, &getpolicy, sizeof(getpolicy));
280 xc_interface_close(xc_handle);
282 if (rc == 0) {
283 struct acm_policy_buffer *header =
284 (struct acm_policy_buffer *)pull_buffer;
285 if (ntohl(header->len) < sizeof(pull_buffer))
286 len = ntohl(header->len);
287 } else {
288 len = 0;
289 }
291 result = Py_BuildValue("is#", rc, pull_buffer, len);
292 return result;
293 }
296 static PyObject *relabel_domains(PyObject *self, PyObject *args)
297 {
298 struct acm_relabel_doms reldoms;
299 int xc_handle, rc;
300 char *relabel_rules = NULL;
301 int rel_rules_len = 0;
302 uint errarray_mbrs = 20 * 2;
303 uint32_t error_array[errarray_mbrs];
304 PyObject *result;
305 uint len;
307 memset(&reldoms, 0x0, sizeof(reldoms));
309 if (!PyArg_ParseTuple(args, "s#" ,&relabel_rules, &rel_rules_len)) {
310 PyErr_SetString(PyExc_TypeError, bad_arg);
311 return NULL;
312 }
314 reldoms.relabel_map_size = rel_rules_len;
315 reldoms.errarray_size = sizeof(error_array);
317 set_xen_guest_handle(reldoms.relabel_map, relabel_rules);
318 set_xen_guest_handle(reldoms.err_array, error_array);
320 if ((xc_handle = xc_interface_open()) <= 0) {
321 PyErr_SetString(PyExc_IOError, ctrlif_op);
322 return NULL;
323 }
325 rc = xc_acm_op(xc_handle, ACMOP_relabeldoms, &reldoms, sizeof(reldoms));
327 xc_interface_close(xc_handle);
330 /* only pass the filled error codes */
331 for (len = 0; (len + 1) < errarray_mbrs; len += 2) {
332 if (error_array[len] == 0) {
333 len *= sizeof(error_array[0]);
334 break;
335 }
336 }
338 result = Py_BuildValue("is#", rc, error_array, len);
339 return result;
340 }
343 /*=================General Python Extension Declarations=================*/
345 /* methods */
346 static PyMethodDef acmMethods[] = {
347 {"policy", policy, METH_VARARGS, "Retrieve Active ACM Policy Reference Name"},
348 {"getssid", getssid, METH_VARARGS, "Retrieve label information and ssidref for a domain"},
349 {"getdecision", getdecision, METH_VARARGS, "Retrieve ACM access control decision"},
350 {"chgpolicy", chgpolicy, METH_VARARGS, "Change the policy in one step"},
351 {"getpolicy", getpolicy, METH_NOARGS , "Get the binary policy from the hypervisor"},
352 {"relabel_domains", relabel_domains, METH_VARARGS, "Relabel domains"},
353 /* end of list (extend list above this line) */
354 {NULL, NULL, 0, NULL}
355 };
357 /* inits */
358 PyMODINIT_FUNC initacm(void)
359 {
360 PyObject *m = Py_InitModule("acm", acmMethods);
361 acm_error_obj = PyErr_NewException("acm.Error", PyExc_RuntimeError, NULL);
362 Py_INCREF(acm_error_obj);
363 PyModule_AddObject(m, "Error", acm_error_obj);
364 }