direct-io.hg

view tools/security/secpol_tool.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 21e6625a6c01
line source
1 /****************************************************************
2 * secpol_tool.c
3 *
4 * Copyright (C) 2005 IBM Corporation
5 *
6 * Authors:
7 * Reiner Sailer <sailer@watson.ibm.com>
8 * Stefan Berger <stefanb@watson.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 * sHype policy management tool. This code runs in a domain and
16 * manages the Xen security policy by interacting with the
17 * Xen access control module via the privcmd device,
18 * which is translated into a acm_op hypercall into Xen.
19 *
20 * indent -i4 -kr -nut
21 */
24 #include <unistd.h>
25 #include <stdio.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <getopt.h>
29 #include <sys/mman.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <stdlib.h>
33 #include <sys/ioctl.h>
34 #include <string.h>
35 #include <netinet/in.h>
36 #include <stdint.h>
37 #include <xen/acm.h>
38 #include <xen/acm_ops.h>
40 #include <xenctrl.h>
42 #define PERROR(_m, _a...) \
43 fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
44 errno, strerror(errno))
46 void usage(char *progname)
47 {
48 printf("Usage: %s ACTION\n"
49 "ACTION is one of:\n"
50 "\t getpolicy\n"
51 "\t dumpstats\n"
52 "\t loadpolicy <binary policy file>\n", progname);
53 exit(-1);
54 }
56 /*************************** DUMPS *******************************/
58 void acm_dump_chinesewall_buffer(void *buf, int buflen)
59 {
61 struct acm_chwall_policy_buffer *cwbuf =
62 (struct acm_chwall_policy_buffer *) buf;
63 domaintype_t *ssids, *conflicts, *running_types, *conflict_aggregate;
64 int i, j;
67 if (htonl(cwbuf->policy_code) != ACM_CHINESE_WALL_POLICY) {
68 printf("CHINESE WALL POLICY CODE not found ERROR!!\n");
69 return;
70 }
71 printf("\n\nChinese Wall policy:\n");
72 printf("====================\n");
73 printf("Policy version= %x.\n", ntohl(cwbuf->policy_version));
74 printf("Max Types = %x.\n", ntohl(cwbuf->chwall_max_types));
75 printf("Max Ssidrefs = %x.\n", ntohl(cwbuf->chwall_max_ssidrefs));
76 printf("Max ConfSets = %x.\n", ntohl(cwbuf->chwall_max_conflictsets));
77 printf("Ssidrefs Off = %x.\n", ntohl(cwbuf->chwall_ssid_offset));
78 printf("Conflicts Off = %x.\n",
79 ntohl(cwbuf->chwall_conflict_sets_offset));
80 printf("Runing T. Off = %x.\n",
81 ntohl(cwbuf->chwall_running_types_offset));
82 printf("C. Agg. Off = %x.\n",
83 ntohl(cwbuf->chwall_conflict_aggregate_offset));
84 printf("\nSSID To CHWALL-Type matrix:\n");
86 ssids = (domaintype_t *) (buf + ntohl(cwbuf->chwall_ssid_offset));
87 for (i = 0; i < ntohl(cwbuf->chwall_max_ssidrefs); i++) {
88 printf("\n ssidref%2x: ", i);
89 for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++)
90 printf("%02x ",
91 ntohs(ssids[i * ntohl(cwbuf->chwall_max_types) + j]));
92 }
93 printf("\n\nConfict Sets:\n");
94 conflicts =
95 (domaintype_t *) (buf + ntohl(cwbuf->chwall_conflict_sets_offset));
96 for (i = 0; i < ntohl(cwbuf->chwall_max_conflictsets); i++) {
97 printf("\n c-set%2x: ", i);
98 for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++)
99 printf("%02x ",
100 ntohs(conflicts
101 [i * ntohl(cwbuf->chwall_max_types) + j]));
102 }
103 printf("\n");
105 printf("\nRunning\nTypes: ");
106 if (ntohl(cwbuf->chwall_running_types_offset)) {
107 running_types =
108 (domaintype_t *) (buf +
109 ntohl(cwbuf->chwall_running_types_offset));
110 for (i = 0; i < ntohl(cwbuf->chwall_max_types); i++) {
111 printf("%02x ", ntohs(running_types[i]));
112 }
113 printf("\n");
114 } else {
115 printf("Not Reported!\n");
116 }
117 printf("\nConflict\nAggregate Set: ");
118 if (ntohl(cwbuf->chwall_conflict_aggregate_offset)) {
119 conflict_aggregate =
120 (domaintype_t *) (buf +
121 ntohl(cwbuf->
122 chwall_conflict_aggregate_offset));
123 for (i = 0; i < ntohl(cwbuf->chwall_max_types); i++) {
124 printf("%02x ", ntohs(conflict_aggregate[i]));
125 }
126 printf("\n\n");
127 } else {
128 printf("Not Reported!\n");
129 }
130 }
132 void acm_dump_ste_buffer(void *buf, int buflen)
133 {
135 struct acm_ste_policy_buffer *stebuf =
136 (struct acm_ste_policy_buffer *) buf;
137 domaintype_t *ssids;
138 int i, j;
141 if (ntohl(stebuf->policy_code) != ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
142 printf("SIMPLE TYPE ENFORCEMENT POLICY CODE not found ERROR!!\n");
143 return;
144 }
145 printf("\nSimple Type Enforcement policy:\n");
146 printf("===============================\n");
147 printf("Policy version= %x.\n", ntohl(stebuf->policy_version));
148 printf("Max Types = %x.\n", ntohl(stebuf->ste_max_types));
149 printf("Max Ssidrefs = %x.\n", ntohl(stebuf->ste_max_ssidrefs));
150 printf("Ssidrefs Off = %x.\n", ntohl(stebuf->ste_ssid_offset));
151 printf("\nSSID To STE-Type matrix:\n");
153 ssids = (domaintype_t *) (buf + ntohl(stebuf->ste_ssid_offset));
154 for (i = 0; i < ntohl(stebuf->ste_max_ssidrefs); i++) {
155 printf("\n ssidref%2x: ", i);
156 for (j = 0; j < ntohl(stebuf->ste_max_types); j++)
157 printf("%02x ",
158 ntohs(ssids[i * ntohl(stebuf->ste_max_types) + j]));
159 }
160 printf("\n\n");
161 }
163 void acm_dump_policy_buffer(void *buf, int buflen)
164 {
165 struct acm_policy_buffer *pol = (struct acm_policy_buffer *) buf;
166 char *policy_reference_name =
167 (buf + ntohl(pol->policy_reference_offset) +
168 sizeof(struct acm_policy_reference_buffer));
169 printf("\nPolicy dump:\n");
170 printf("============\n");
171 printf("POLICY REFERENCE = %s.\n", policy_reference_name);
172 printf("PolicyVer = %x.\n", ntohl(pol->policy_version));
173 printf("Magic = %x.\n", ntohl(pol->magic));
174 printf("Len = %x.\n", ntohl(pol->len));
175 printf("Primary = %s (c=%x, off=%x).\n",
176 ACM_POLICY_NAME(ntohl(pol->primary_policy_code)),
177 ntohl(pol->primary_policy_code),
178 ntohl(pol->primary_buffer_offset));
179 printf("Secondary = %s (c=%x, off=%x).\n",
180 ACM_POLICY_NAME(ntohl(pol->secondary_policy_code)),
181 ntohl(pol->secondary_policy_code),
182 ntohl(pol->secondary_buffer_offset));
183 switch (ntohl(pol->primary_policy_code)) {
184 case ACM_CHINESE_WALL_POLICY:
185 acm_dump_chinesewall_buffer(buf +
186 ntohl(pol->primary_buffer_offset),
187 ntohl(pol->len) -
188 ntohl(pol->primary_buffer_offset));
189 break;
191 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
192 acm_dump_ste_buffer(buf + ntohl(pol->primary_buffer_offset),
193 ntohl(pol->len) -
194 ntohl(pol->primary_buffer_offset));
195 break;
197 case ACM_NULL_POLICY:
198 printf("Primary policy is NULL Policy (n/a).\n");
199 break;
201 default:
202 printf("UNKNOWN POLICY!\n");
203 }
205 switch (ntohl(pol->secondary_policy_code)) {
206 case ACM_CHINESE_WALL_POLICY:
207 acm_dump_chinesewall_buffer(buf +
208 ntohl(pol->secondary_buffer_offset),
209 ntohl(pol->len) -
210 ntohl(pol->secondary_buffer_offset));
211 break;
213 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
214 acm_dump_ste_buffer(buf + ntohl(pol->secondary_buffer_offset),
215 ntohl(pol->len) -
216 ntohl(pol->secondary_buffer_offset));
217 break;
219 case ACM_NULL_POLICY:
220 printf("Secondary policy is NULL Policy (n/a).\n");
221 break;
223 default:
224 printf("UNKNOWN POLICY!\n");
225 }
226 }
228 /******************************* get policy ******************************/
230 #define PULL_CACHE_SIZE 8192
231 uint8_t pull_buffer[PULL_CACHE_SIZE];
232 int acm_domain_getpolicy(int xc_handle)
233 {
234 struct acm_getpolicy getpolicy;
235 int ret;
237 memset(pull_buffer, 0x00, sizeof(pull_buffer));
238 getpolicy.interface_version = ACM_INTERFACE_VERSION;
239 getpolicy.pullcache = (void *) pull_buffer;
240 getpolicy.pullcache_size = sizeof(pull_buffer);
241 ret = xc_acm_op(xc_handle, ACMOP_getpolicy, &getpolicy, sizeof(getpolicy));
243 if (ret < 0) {
244 printf("ACM operation failed: errno=%d\n", errno);
245 if (errno == EACCES)
246 fprintf(stderr, "ACM operation failed -- need to"
247 " rebuild the user-space tool set?\n");
248 }
250 /* dump policy */
251 acm_dump_policy_buffer(pull_buffer, sizeof(pull_buffer));
252 return ret;
253 }
255 /************************ load binary policy ******************************/
257 int acm_domain_loadpolicy(int xc_handle, const char *filename)
258 {
259 struct stat mystat;
260 int ret, fd;
261 off_t len;
262 uint8_t *buffer;
264 if ((ret = stat(filename, &mystat))) {
265 printf("File %s not found.\n", filename);
266 goto out;
267 }
269 len = mystat.st_size;
270 if ((buffer = malloc(len)) == NULL) {
271 ret = -ENOMEM;
272 goto out;
273 }
274 if ((fd = open(filename, O_RDONLY)) <= 0) {
275 ret = -ENOENT;
276 printf("File %s not found.\n", filename);
277 goto free_out;
278 }
279 if (len == read(fd, buffer, len)) {
280 struct acm_setpolicy setpolicy;
281 /* dump it and then push it down into xen/acm */
282 acm_dump_policy_buffer(buffer, len);
283 setpolicy.interface_version = ACM_INTERFACE_VERSION;
284 setpolicy.pushcache = (void *) buffer;
285 setpolicy.pushcache_size = len;
286 ret = xc_acm_op(xc_handle, ACMOP_setpolicy, &setpolicy, sizeof(setpolicy));
288 if (ret)
289 printf
290 ("ERROR setting policy.\n");
291 else
292 printf("Successfully changed policy.\n");
294 } else {
295 ret = -1;
296 }
297 close(fd);
298 free_out:
299 free(buffer);
300 out:
301 return ret;
302 }
304 /************************ dump hook statistics ******************************/
305 void dump_ste_stats(struct acm_ste_stats_buffer *ste_stats)
306 {
307 printf("STE-Policy Security Hook Statistics:\n");
308 printf("ste: event_channel eval_count = %d\n",
309 ntohl(ste_stats->ec_eval_count));
310 printf("ste: event_channel denied_count = %d\n",
311 ntohl(ste_stats->ec_denied_count));
312 printf("ste: event_channel cache_hit_count = %d\n",
313 ntohl(ste_stats->ec_cachehit_count));
314 printf("ste:\n");
315 printf("ste: grant_table eval_count = %d\n",
316 ntohl(ste_stats->gt_eval_count));
317 printf("ste: grant_table denied_count = %d\n",
318 ntohl(ste_stats->gt_denied_count));
319 printf("ste: grant_table cache_hit_count = %d\n",
320 ntohl(ste_stats->gt_cachehit_count));
321 }
323 #define PULL_STATS_SIZE 8192
324 int acm_domain_dumpstats(int xc_handle)
325 {
326 uint8_t stats_buffer[PULL_STATS_SIZE];
327 struct acm_dumpstats dumpstats;
328 int ret;
329 struct acm_stats_buffer *stats;
331 memset(stats_buffer, 0x00, sizeof(stats_buffer));
332 dumpstats.interface_version = ACM_INTERFACE_VERSION;
333 dumpstats.pullcache = (void *) stats_buffer;
334 dumpstats.pullcache_size = sizeof(stats_buffer);
335 ret = xc_acm_op(xc_handle, ACMOP_dumpstats, &dumpstats, sizeof(dumpstats));
337 if (ret < 0) {
338 printf
339 ("ERROR dumping policy stats. Try 'xm dmesg' to see details.\n");
340 return ret;
341 }
342 stats = (struct acm_stats_buffer *) stats_buffer;
344 printf("\nPolicy dump:\n");
345 printf("============\n");
346 printf("Magic = %x.\n", ntohl(stats->magic));
347 printf("Len = %x.\n", ntohl(stats->len));
349 switch (ntohl(stats->primary_policy_code)) {
350 case ACM_NULL_POLICY:
351 printf("NULL Policy: No statistics apply.\n");
352 break;
354 case ACM_CHINESE_WALL_POLICY:
355 printf("Chinese Wall Policy: No statistics apply.\n");
356 break;
358 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
359 dump_ste_stats((struct acm_ste_stats_buffer *) (stats_buffer +
360 ntohl(stats->
361 primary_stats_offset)));
362 break;
364 default:
365 printf("UNKNOWN PRIMARY POLICY ERROR!\n");
366 }
368 switch (ntohl(stats->secondary_policy_code)) {
369 case ACM_NULL_POLICY:
370 printf("NULL Policy: No statistics apply.\n");
371 break;
373 case ACM_CHINESE_WALL_POLICY:
374 printf("Chinese Wall Policy: No statistics apply.\n");
375 break;
377 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
378 dump_ste_stats((struct acm_ste_stats_buffer *) (stats_buffer +
379 ntohl(stats->
380 secondary_stats_offset)));
381 break;
383 default:
384 printf("UNKNOWN SECONDARY POLICY ERROR!\n");
385 }
386 return ret;
387 }
389 /***************************** main **************************************/
391 int main(int argc, char **argv)
392 {
394 int xc_handle, ret = 0;
396 if (argc < 2)
397 usage(argv[0]);
399 if ((xc_handle = xc_interface_open()) <= 0) {
400 printf("ERROR: Could not open xen privcmd device!\n");
401 exit(-1);
402 }
404 if (!strcmp(argv[1], "getpolicy")) {
405 if (argc != 2)
406 usage(argv[0]);
407 ret = acm_domain_getpolicy(xc_handle);
408 } else if (!strcmp(argv[1], "loadpolicy")) {
409 if (argc != 3)
410 usage(argv[0]);
411 ret = acm_domain_loadpolicy(xc_handle, argv[2]);
412 } else if (!strcmp(argv[1], "dumpstats")) {
413 if (argc != 2)
414 usage(argv[0]);
415 ret = acm_domain_dumpstats(xc_handle);
416 } else
417 usage(argv[0]);
419 xc_interface_close(xc_handle);
420 return ret;
421 }