direct-io.hg

view tools/python/xen/lowlevel/acm/acm.c @ 10057:0f16f0871dc9

[ACM] Replace the union structure parameter of the ACM hypercalls
with command-specific request structures. It aligns the ACM
hypercalls with the way parameters are passed in the event channel
hypercalls.

Advantages include backward-compatibility regarding old guests when
new calls are added and clarity of the code.

Signed-off by: Reiner Sailer <sailer@us.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Sun May 21 19:05:31 2006 +0100 (2006-05-21)
parents 24dbb153ab39
children c1163951ee2f
line source
1 /****************************************************************
2 * acm.c
3 *
4 * Copyright (C) 2006 IBM Corporation
5 *
6 * Authors:
7 * Reiner Sailer <sailer@watson.ibm.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 *
14 * ACM low-level code that allows Python control code to leverage
15 * the ACM hypercall interface to retrieve real-time information
16 * from the Xen hypervisor security module.
17 *
18 * indent -i4 -kr -nut
19 */
20 #include <Python.h>
22 #include <stdio.h>
23 #include <fcntl.h>
24 #include <sys/mman.h>
25 #include <sys/types.h>
26 #include <stdlib.h>
27 #include <sys/ioctl.h>
28 #include <netinet/in.h>
29 #include <xen/acm.h>
30 #include <xen/acm_ops.h>
32 #include <xenctrl.h>
34 #define PERROR(_m, _a...) \
35 fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
36 errno, strerror(errno))
38 /* generic shared function */
39 void * __getssid(int domid, uint32_t *buflen)
40 {
41 struct acm_getssid getssid;
42 int xc_handle;
43 #define SSID_BUFFER_SIZE 4096
44 void *buf = NULL;
46 if ((xc_handle = xc_interface_open()) < 0) {
47 goto out1;
48 }
49 if ((buf = malloc(SSID_BUFFER_SIZE)) == NULL) {
50 PERROR("acm.policytype: Could not allocate ssid buffer!\n");
51 goto out2;
52 }
53 memset(buf, 0, SSID_BUFFER_SIZE);
54 getssid.interface_version = ACM_INTERFACE_VERSION;
55 getssid.ssidbuf = buf;
56 getssid.ssidbuf_size = SSID_BUFFER_SIZE;
57 getssid.get_ssid_by = DOMAINID;
58 getssid.id.domainid = domid;
60 if (xc_acm_op(xc_handle, ACMOP_getssid, &getssid, sizeof(getssid)) < 0) {
61 if (errno == EACCES)
62 PERROR("ACM operation failed.");
63 free(buf);
64 buf = NULL;
65 goto out2;
66 } else {
67 *buflen = SSID_BUFFER_SIZE;
68 goto out2;
69 }
70 out2:
71 xc_interface_close(xc_handle);
72 out1:
73 return buf;
74 }
77 /* retrieve the policytype indirectly by retrieving the
78 * ssidref for domain 0 (always exists) */
79 static PyObject *policy(PyObject * self, PyObject * args)
80 {
81 /* out */
82 char *policyreference;
83 PyObject *ret = NULL;
84 void *ssid_buffer;
85 uint32_t buf_len;
87 if (!PyArg_ParseTuple(args, "", NULL)) {
88 goto out1;
89 }
90 ssid_buffer = __getssid(0, &buf_len);
91 if (ssid_buffer == NULL) {
92 goto out1;
93 } else if (buf_len < sizeof(struct acm_ssid_buffer)) {
94 goto out2;
95 } else {
96 struct acm_ssid_buffer *ssid = (struct acm_ssid_buffer *)ssid_buffer;
97 policyreference = (char *)(ssid_buffer + ssid->policy_reference_offset
98 + sizeof (struct acm_policy_reference_buffer));
99 }
100 ret = Py_BuildValue("s", policyreference);
101 out2:
102 free(ssid_buffer);
103 out1:
104 return ret;
105 }
108 /* retrieve ssid info for a domain domid*/
109 static PyObject *getssid(PyObject * self, PyObject * args)
110 {
111 /* in */
112 uint32_t domid;
113 /* out */
114 char *policytype, *policyreference;
115 uint32_t ssidref;
117 void *ssid_buffer;
118 uint32_t buf_len;
120 if (!PyArg_ParseTuple(args, "i", &domid)) {
121 return NULL;
122 }
123 ssid_buffer = __getssid(domid, &buf_len);
124 if (ssid_buffer == NULL) {
125 return NULL;
126 } else if (buf_len < sizeof(struct acm_ssid_buffer)) {
127 free(ssid_buffer);
128 return NULL;
129 } else {
130 struct acm_ssid_buffer *ssid = (struct acm_ssid_buffer *) ssid_buffer;
131 policytype = ACM_POLICY_NAME(ssid->secondary_policy_code << 4 |
132 ssid->primary_policy_code);
133 ssidref = ssid->ssidref;
134 policyreference = (char *)(ssid_buffer + ssid->policy_reference_offset
135 + sizeof (struct acm_policy_reference_buffer));
136 }
137 free(ssid_buffer);
138 return Py_BuildValue("{s:s,s:s,s:i}",
139 "policyreference", policyreference,
140 "policytype", policytype,
141 "ssidref", ssidref);
142 }
145 /* retrieve access decision based on domain ids or ssidrefs */
146 static PyObject *getdecision(PyObject * self, PyObject * args)
147 {
148 char *arg1_name, *arg1, *arg2_name, *arg2, *decision = NULL;
149 struct acm_getdecision getdecision;
150 int xc_handle;
152 if (!PyArg_ParseTuple(args, "ssss", &arg1_name, &arg1, &arg2_name, &arg2)) {
153 return NULL;
154 }
156 if ((xc_handle = xc_interface_open()) <= 0) {
157 PERROR("Could not open xen privcmd device!\n");
158 return NULL;
159 }
161 if ((strcmp(arg1_name, "domid") && strcmp(arg1_name, "ssidref")) ||
162 (strcmp(arg2_name, "domid") && strcmp(arg2_name, "ssidref")))
163 return NULL;
165 getdecision.interface_version = ACM_INTERFACE_VERSION;
166 getdecision.hook = SHARING;
167 if (!strcmp(arg1_name, "domid")) {
168 getdecision.get_decision_by1 = DOMAINID;
169 getdecision.id1.domainid = atoi(arg1);
170 } else {
171 getdecision.get_decision_by1 = SSIDREF;
172 getdecision.id1.ssidref = atol(arg1);
173 }
174 if (!strcmp(arg2_name, "domid")) {
175 getdecision.get_decision_by2 = DOMAINID;
176 getdecision.id2.domainid = atoi(arg2);
177 } else {
178 getdecision.get_decision_by2 = SSIDREF;
179 getdecision.id2.ssidref = atol(arg2);
180 }
182 if (xc_acm_op(xc_handle, ACMOP_getdecision, &getdecision, sizeof(getdecision)) < 0) {
183 if (errno == EACCES)
184 PERROR("ACM operation failed.");
185 }
187 xc_interface_close(xc_handle);
189 if (getdecision.acm_decision == ACM_ACCESS_PERMITTED)
190 decision = "PERMITTED";
191 else if (getdecision.acm_decision == ACM_ACCESS_DENIED)
192 decision = "DENIED";
194 return Py_BuildValue("s", decision);
195 }
197 /*=================General Python Extension Declarations=================*/
199 /* methods */
200 static PyMethodDef acmMethods[] = {
201 {"policy", policy, METH_VARARGS, "Retrieve Active ACM Policy Reference Name"},
202 {"getssid", getssid, METH_VARARGS, "Retrieve label information and ssidref for a domain"},
203 {"getdecision", getdecision, METH_VARARGS, "Retrieve ACM access control decision"},
204 /* end of list (extend list above this line) */
205 {NULL, NULL, 0, NULL}
206 };
208 /* inits */
209 PyMODINIT_FUNC initacm(void)
210 {
211 Py_InitModule("acm", acmMethods);
212 }