ia64/xen-unstable

view tools/security/secpol_tool.c @ 19731:01748ccc4da3

Intel VT-d: fix Stoakley boot issue with iommu=1

Signed-off-by: Weidong Han <Weidong.han@intel.com>
Signed-off-by: Allen Kay <allen.m.kay@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 09:25:50 2009 +0100 (2009-06-05)
parents 2e5e948bf69d
children
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/xsm/acm.h>
38 #include <xen/xsm/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"
53 "\t dumppolicy <binary policy file> [Dom-0 ssidref]\n",
54 progname);
55 exit(-1);
56 }
58 /*************************** DUMPS *******************************/
60 void acm_dump_chinesewall_buffer(void *buf, int buflen, uint16_t chwall_ref)
61 {
63 struct acm_chwall_policy_buffer *cwbuf =
64 (struct acm_chwall_policy_buffer *) buf;
65 domaintype_t *ssids, *conflicts, *running_types, *conflict_aggregate;
66 int i, j;
69 if (htonl(cwbuf->policy_code) != ACM_CHINESE_WALL_POLICY) {
70 printf("CHINESE WALL POLICY CODE not found ERROR!!\n");
71 return;
72 }
73 printf("\n\nChinese Wall policy:\n");
74 printf("====================\n");
75 printf("Policy version= %x.\n", ntohl(cwbuf->policy_version));
76 printf("Max Types = %x.\n", ntohl(cwbuf->chwall_max_types));
77 printf("Max Ssidrefs = %x.\n", ntohl(cwbuf->chwall_max_ssidrefs));
78 printf("Max ConfSets = %x.\n", ntohl(cwbuf->chwall_max_conflictsets));
79 printf("Ssidrefs Off = %x.\n", ntohl(cwbuf->chwall_ssid_offset));
80 printf("Conflicts Off = %x.\n",
81 ntohl(cwbuf->chwall_conflict_sets_offset));
82 printf("Runing T. Off = %x.\n",
83 ntohl(cwbuf->chwall_running_types_offset));
84 printf("C. Agg. Off = %x.\n",
85 ntohl(cwbuf->chwall_conflict_aggregate_offset));
86 printf("\nSSID To CHWALL-Type matrix:\n");
88 ssids = (domaintype_t *) (buf + ntohl(cwbuf->chwall_ssid_offset));
89 for (i = 0; i < ntohl(cwbuf->chwall_max_ssidrefs); i++) {
90 printf("\n ssidref%2x: ", i);
91 for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++)
92 printf("%02x ",
93 ntohs(ssids[i * ntohl(cwbuf->chwall_max_types) + j]));
94 if (i == chwall_ref)
95 printf(" <-- Domain-0");
96 }
97 printf("\n\nConfict Sets:\n");
98 conflicts =
99 (domaintype_t *) (buf + ntohl(cwbuf->chwall_conflict_sets_offset));
100 for (i = 0; i < ntohl(cwbuf->chwall_max_conflictsets); i++) {
101 printf("\n c-set%2x: ", i);
102 for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++)
103 printf("%02x ",
104 ntohs(conflicts
105 [i * ntohl(cwbuf->chwall_max_types) + j]));
106 }
107 printf("\n");
109 printf("\nRunning\nTypes: ");
110 if (ntohl(cwbuf->chwall_running_types_offset)) {
111 running_types =
112 (domaintype_t *) (buf +
113 ntohl(cwbuf->chwall_running_types_offset));
114 for (i = 0; i < ntohl(cwbuf->chwall_max_types); i++) {
115 printf("%02x ", ntohs(running_types[i]));
116 }
117 printf("\n");
118 } else {
119 printf("Not Reported!\n");
120 }
121 printf("\nConflict\nAggregate Set: ");
122 if (ntohl(cwbuf->chwall_conflict_aggregate_offset)) {
123 conflict_aggregate =
124 (domaintype_t *) (buf +
125 ntohl(cwbuf->
126 chwall_conflict_aggregate_offset));
127 for (i = 0; i < ntohl(cwbuf->chwall_max_types); i++) {
128 printf("%02x ", ntohs(conflict_aggregate[i]));
129 }
130 printf("\n\n");
131 } else {
132 printf("Not Reported!\n");
133 }
134 }
136 void acm_dump_ste_buffer(void *buf, int buflen, uint16_t ste_ref)
137 {
139 struct acm_ste_policy_buffer *stebuf =
140 (struct acm_ste_policy_buffer *) buf;
141 domaintype_t *ssids;
142 int i, j;
145 if (ntohl(stebuf->policy_code) != ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
146 printf("SIMPLE TYPE ENFORCEMENT POLICY CODE not found ERROR!!\n");
147 return;
148 }
149 printf("\nSimple Type Enforcement policy:\n");
150 printf("===============================\n");
151 printf("Policy version= %x.\n", ntohl(stebuf->policy_version));
152 printf("Max Types = %x.\n", ntohl(stebuf->ste_max_types));
153 printf("Max Ssidrefs = %x.\n", ntohl(stebuf->ste_max_ssidrefs));
154 printf("Ssidrefs Off = %x.\n", ntohl(stebuf->ste_ssid_offset));
155 printf("\nSSID To STE-Type matrix:\n");
157 ssids = (domaintype_t *) (buf + ntohl(stebuf->ste_ssid_offset));
158 for (i = 0; i < ntohl(stebuf->ste_max_ssidrefs); i++) {
159 printf("\n ssidref%2x: ", i);
160 for (j = 0; j < ntohl(stebuf->ste_max_types); j++)
161 printf("%02x ",
162 ntohs(ssids[i * ntohl(stebuf->ste_max_types) + j]));
163 if (i == ste_ref)
164 printf(" <-- Domain-0");
165 }
166 printf("\n\n");
167 }
169 void acm_dump_policy_buffer(void *buf, int buflen,
170 uint16_t chwall_ref, uint16_t ste_ref)
171 {
172 struct acm_policy_buffer *pol = (struct acm_policy_buffer *) buf;
173 char *policy_reference_name =
174 (buf + ntohl(pol->policy_reference_offset) +
175 sizeof(struct acm_policy_reference_buffer));
176 printf("\nPolicy dump:\n");
177 printf("============\n");
178 printf("POLICY REFERENCE = %s.\n", policy_reference_name);
179 printf("PolicyVer = %x.\n", ntohl(pol->policy_version));
180 printf("XML Vers. = %d.%d\n",
181 ntohl(pol->xml_pol_version.major),
182 ntohl(pol->xml_pol_version.minor));
183 printf("Magic = %x.\n", ntohl(pol->magic));
184 printf("Len = %x.\n", ntohl(pol->len));
185 printf("Primary = %s (c=%x, off=%x).\n",
186 ACM_POLICY_NAME(ntohl(pol->primary_policy_code)),
187 ntohl(pol->primary_policy_code),
188 ntohl(pol->primary_buffer_offset));
189 printf("Secondary = %s (c=%x, off=%x).\n",
190 ACM_POLICY_NAME(ntohl(pol->secondary_policy_code)),
191 ntohl(pol->secondary_policy_code),
192 ntohl(pol->secondary_buffer_offset));
193 switch (ntohl(pol->primary_policy_code)) {
194 case ACM_CHINESE_WALL_POLICY:
195 acm_dump_chinesewall_buffer(buf + ntohl(pol->primary_buffer_offset),
196 ntohl(pol->len) -
197 ntohl(pol->primary_buffer_offset),
198 chwall_ref);
199 break;
201 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
202 acm_dump_ste_buffer(buf + ntohl(pol->primary_buffer_offset),
203 ntohl(pol->len) -
204 ntohl(pol->primary_buffer_offset),
205 ste_ref);
206 break;
208 case ACM_NULL_POLICY:
209 printf("Primary policy is NULL Policy (n/a).\n");
210 break;
212 default:
213 printf("UNKNOWN POLICY!\n");
214 }
216 switch (ntohl(pol->secondary_policy_code)) {
217 case ACM_CHINESE_WALL_POLICY:
218 acm_dump_chinesewall_buffer(buf + ntohl(pol->secondary_buffer_offset),
219 ntohl(pol->len) -
220 ntohl(pol->secondary_buffer_offset),
221 chwall_ref);
222 break;
224 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
225 acm_dump_ste_buffer(buf + ntohl(pol->secondary_buffer_offset),
226 ntohl(pol->len) -
227 ntohl(pol->secondary_buffer_offset),
228 ste_ref);
229 break;
231 case ACM_NULL_POLICY:
232 printf("Secondary policy is NULL Policy (n/a).\n");
233 break;
235 default:
236 printf("UNKNOWN POLICY!\n");
237 }
238 }
240 /************************** get dom0 ssidref *****************************/
241 int acm_get_ssidref(int xc_handle, int domid, uint16_t *chwall_ref,
242 uint16_t *ste_ref)
243 {
244 int ret;
245 struct acm_getssid getssid;
246 char buf[4096];
247 struct acm_ssid_buffer *ssid = (struct acm_ssid_buffer *)buf;
248 set_xen_guest_handle(getssid.ssidbuf, buf);
249 getssid.ssidbuf_size = sizeof(buf);
250 getssid.get_ssid_by = ACM_GETBY_domainid;
251 getssid.id.domainid = domid;
252 ret = xc_acm_op(xc_handle, ACMOP_getssid, &getssid, sizeof(getssid));
253 if (ret == 0) {
254 *chwall_ref = ssid->ssidref & 0xffff;
255 *ste_ref = ssid->ssidref >> 16;
256 }
257 return ret;
258 }
260 /******************************* get policy ******************************/
262 #define PULL_CACHE_SIZE 8192
263 uint8_t pull_buffer[PULL_CACHE_SIZE];
265 int acm_domain_getpolicy(int xc_handle)
266 {
267 struct acm_getpolicy getpolicy;
268 int ret;
269 uint16_t chwall_ref, ste_ref;
271 memset(pull_buffer, 0x00, sizeof(pull_buffer));
272 set_xen_guest_handle(getpolicy.pullcache, pull_buffer);
273 getpolicy.pullcache_size = sizeof(pull_buffer);
274 ret = xc_acm_op(xc_handle, ACMOP_getpolicy, &getpolicy, sizeof(getpolicy));
275 if (ret >= 0) {
276 ret = acm_get_ssidref(xc_handle, 0, &chwall_ref, &ste_ref);
277 }
279 if (ret < 0) {
280 printf("ACM operation failed: errno=%d\n", errno);
281 if (errno == EACCES)
282 fprintf(stderr, "ACM operation failed -- need to"
283 " rebuild the user-space tool set?\n");
284 }
286 /* dump policy */
287 acm_dump_policy_buffer(pull_buffer, sizeof(pull_buffer),
288 chwall_ref, ste_ref);
290 return ret;
291 }
293 /************************ dump binary policy ******************************/
295 static int load_file(const char *filename,
296 uint8_t **buffer, off_t *len)
297 {
298 struct stat mystat;
299 int ret = 0;
300 int fd;
302 if ((ret = stat(filename, &mystat)) != 0) {
303 printf("File %s not found.\n", filename);
304 ret = errno;
305 goto out;
306 }
308 *len = mystat.st_size;
310 if ((*buffer = malloc(*len)) == NULL) {
311 ret = -ENOMEM;
312 goto out;
313 }
315 if ((fd = open(filename, O_RDONLY)) <= 0) {
316 ret = -ENOENT;
317 printf("File %s not found.\n", filename);
318 goto free_out;
319 }
321 if (*len == read(fd, *buffer, *len))
322 return 0;
324 free_out:
325 free(*buffer);
326 *buffer = NULL;
327 *len = 0;
328 out:
329 return ret;
330 }
332 static int acm_domain_dumppolicy(const char *filename, uint32_t ssidref)
333 {
334 uint8_t *buffer = NULL;
335 off_t len;
336 int ret = 0;
337 uint16_t chwall_ssidref, ste_ssidref;
339 chwall_ssidref = (ssidref ) & 0xffff;
340 ste_ssidref = (ssidref >> 16) & 0xffff;
342 if ((ret = load_file(filename, &buffer, &len)) == 0) {
343 acm_dump_policy_buffer(buffer, len, chwall_ssidref, ste_ssidref);
344 free(buffer);
345 }
347 return ret;
348 }
350 /************************ load binary policy ******************************/
352 int acm_domain_loadpolicy(int xc_handle, const char *filename)
353 {
354 int ret;
355 off_t len;
356 uint8_t *buffer;
357 uint16_t chwall_ssidref, ste_ssidref;
358 struct acm_setpolicy setpolicy;
360 ret = load_file(filename, &buffer, &len);
361 if (ret != 0)
362 goto out;
364 ret = acm_get_ssidref(xc_handle, 0, &chwall_ssidref, &ste_ssidref);
365 if (ret < 0)
366 goto free_out;
368 /* dump it and then push it down into xen/acm */
369 acm_dump_policy_buffer(buffer, len, chwall_ssidref, ste_ssidref);
370 set_xen_guest_handle(setpolicy.pushcache, buffer);
371 setpolicy.pushcache_size = len;
372 ret = xc_acm_op(xc_handle, ACMOP_setpolicy, &setpolicy, sizeof(setpolicy));
374 if (ret) {
375 printf("ERROR setting policy.\n");
376 } else {
377 printf("Successfully changed policy.\n");
378 }
380 free_out:
381 free(buffer);
382 out:
383 return ret;
384 }
386 /************************ dump hook statistics ******************************/
387 void dump_ste_stats(struct acm_ste_stats_buffer *ste_stats)
388 {
389 printf("STE-Policy Security Hook Statistics:\n");
390 printf("ste: event_channel eval_count = %d\n",
391 ntohl(ste_stats->ec_eval_count));
392 printf("ste: event_channel denied_count = %d\n",
393 ntohl(ste_stats->ec_denied_count));
394 printf("ste: event_channel cache_hit_count = %d\n",
395 ntohl(ste_stats->ec_cachehit_count));
396 printf("ste:\n");
397 printf("ste: grant_table eval_count = %d\n",
398 ntohl(ste_stats->gt_eval_count));
399 printf("ste: grant_table denied_count = %d\n",
400 ntohl(ste_stats->gt_denied_count));
401 printf("ste: grant_table cache_hit_count = %d\n",
402 ntohl(ste_stats->gt_cachehit_count));
403 }
405 #define PULL_STATS_SIZE 8192
406 int acm_domain_dumpstats(int xc_handle)
407 {
408 uint8_t stats_buffer[PULL_STATS_SIZE];
409 struct acm_dumpstats dumpstats;
410 int ret;
411 struct acm_stats_buffer *stats;
413 memset(stats_buffer, 0x00, sizeof(stats_buffer));
414 set_xen_guest_handle(dumpstats.pullcache, stats_buffer);
415 dumpstats.pullcache_size = sizeof(stats_buffer);
416 ret = xc_acm_op(xc_handle, ACMOP_dumpstats, &dumpstats, sizeof(dumpstats));
418 if (ret < 0) {
419 printf
420 ("ERROR dumping policy stats. Try 'xm dmesg' to see details.\n");
421 return ret;
422 }
423 stats = (struct acm_stats_buffer *) stats_buffer;
425 printf("\nPolicy dump:\n");
426 printf("============\n");
427 printf("Magic = %x.\n", ntohl(stats->magic));
428 printf("Len = %x.\n", ntohl(stats->len));
430 switch (ntohl(stats->primary_policy_code)) {
431 case ACM_NULL_POLICY:
432 printf("NULL Policy: No statistics apply.\n");
433 break;
435 case ACM_CHINESE_WALL_POLICY:
436 printf("Chinese Wall Policy: No statistics apply.\n");
437 break;
439 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
440 dump_ste_stats((struct acm_ste_stats_buffer *) (stats_buffer +
441 ntohl(stats->
442 primary_stats_offset)));
443 break;
445 default:
446 printf("UNKNOWN PRIMARY POLICY ERROR!\n");
447 }
449 switch (ntohl(stats->secondary_policy_code)) {
450 case ACM_NULL_POLICY:
451 printf("NULL Policy: No statistics apply.\n");
452 break;
454 case ACM_CHINESE_WALL_POLICY:
455 printf("Chinese Wall Policy: No statistics apply.\n");
456 break;
458 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
459 dump_ste_stats((struct acm_ste_stats_buffer *) (stats_buffer +
460 ntohl(stats->
461 secondary_stats_offset)));
462 break;
464 default:
465 printf("UNKNOWN SECONDARY POLICY ERROR!\n");
466 }
467 return ret;
468 }
470 /***************************** main **************************************/
472 int main(int argc, char **argv)
473 {
475 int xc_handle, ret = 0;
477 if (argc < 2)
478 usage(argv[0]);
481 if (!strcmp(argv[1], "getpolicy")) {
482 if (argc != 2)
483 usage(argv[0]);
485 if ((xc_handle = xc_interface_open()) <= 0) {
486 printf("ERROR: Could not open xen privcmd device!\n");
487 exit(-1);
488 }
490 ret = acm_domain_getpolicy(xc_handle);
492 xc_interface_close(xc_handle);
493 } else if (!strcmp(argv[1], "loadpolicy")) {
494 if (argc != 3)
495 usage(argv[0]);
497 if ((xc_handle = xc_interface_open()) <= 0) {
498 printf("ERROR: Could not open xen privcmd device!\n");
499 exit(-1);
500 }
502 ret = acm_domain_loadpolicy(xc_handle, argv[2]);
504 xc_interface_close(xc_handle);
505 } else if (!strcmp(argv[1], "dumpstats")) {
506 if (argc != 2)
507 usage(argv[0]);
509 if ((xc_handle = xc_interface_open()) <= 0) {
510 printf("ERROR: Could not open xen privcmd device!\n");
511 exit(-1);
512 }
514 ret = acm_domain_dumpstats(xc_handle);
516 xc_interface_close(xc_handle);
517 } else if (!strcmp(argv[1], "dumppolicy")) {
518 uint32_t ssidref = 0xffffffff;
519 if (argc < 3 || argc > 4)
520 usage(argv[0]);
521 if (argc == 4) {
522 if (!sscanf(argv[3], "%i", &ssidref)) {
523 printf("Error: Could not parse ssidref.\n");
524 exit(-1);
525 }
526 }
527 ret = acm_domain_dumppolicy(argv[2], ssidref);
528 } else
529 usage(argv[0]);
531 return ret;
532 }