ia64/xen-unstable

view tools/security/secpol_tool.c @ 6812:26cf3cfd3bed

Switch vcpu hotplugging to use xstransact.
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Tue Sep 13 17:31:13 2005 +0000 (2005-09-13)
parents 291e816acbf4
children b2f4823b6ff0 b35215021b32 9af349b055e5 3233e7ecfa9f
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 a /proc/xen/privcmd proc-ioctl,
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 "secpol_compat.h"
37 #include <xen/acm.h>
38 #include <xen/acm_ops.h>
39 #include <xen/linux/privcmd.h>
41 #define PERROR(_m, _a...) \
42 fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
43 errno, strerror(errno))
45 void usage(char *progname)
46 {
47 printf("Use: %s \n"
48 "\t getpolicy\n"
49 "\t dumpstats\n"
50 "\t loadpolicy <binary policy file>\n"
51 "\t getssid -d <domainid> [-f]\n"
52 "\t getssid -s <ssidref> [-f]\n", progname);
53 exit(-1);
54 }
56 static inline int do_policycmd(int xc_handle, unsigned int cmd,
57 unsigned long data)
58 {
59 return ioctl(xc_handle, cmd, data);
60 }
62 static inline int do_xen_hypercall(int xc_handle,
63 privcmd_hypercall_t * hypercall)
64 {
65 return do_policycmd(xc_handle,
66 IOCTL_PRIVCMD_HYPERCALL,
67 (unsigned long) hypercall);
68 }
70 static inline int do_acm_op(int xc_handle, acm_op_t * op)
71 {
72 int ret = -1;
73 privcmd_hypercall_t hypercall;
75 op->interface_version = ACM_INTERFACE_VERSION;
77 hypercall.op = __HYPERVISOR_acm_op;
78 hypercall.arg[0] = (unsigned long) op;
80 if (mlock(op, sizeof(*op)) != 0)
81 {
82 PERROR("Could not lock memory for Xen policy hypercall");
83 goto out1;
84 }
86 if ((ret = do_xen_hypercall(xc_handle, &hypercall)) < 0)
87 {
88 if (errno == EACCES)
89 fprintf(stderr, "ACM operation failed -- need to"
90 " rebuild the user-space tool set?\n");
91 goto out2;
92 }
94 out2:(void) munlock(op, sizeof(*op));
95 out1:return ret;
96 }
98 /*************************** DUMPS *******************************/
100 void acm_dump_chinesewall_buffer(void *buf, int buflen)
101 {
103 struct acm_chwall_policy_buffer *cwbuf =
104 (struct acm_chwall_policy_buffer *) buf;
105 domaintype_t *ssids, *conflicts, *running_types, *conflict_aggregate;
106 int i, j;
109 if (htonl(cwbuf->policy_code) != ACM_CHINESE_WALL_POLICY)
110 {
111 printf("CHINESE WALL POLICY CODE not found ERROR!!\n");
112 return;
113 }
114 printf("\n\nChinese Wall policy:\n");
115 printf("====================\n");
116 printf("Policy version= %x.\n", ntohl(cwbuf->policy_version));
117 printf("Max Types = %x.\n", ntohl(cwbuf->chwall_max_types));
118 printf("Max Ssidrefs = %x.\n", ntohl(cwbuf->chwall_max_ssidrefs));
119 printf("Max ConfSets = %x.\n", ntohl(cwbuf->chwall_max_conflictsets));
120 printf("Ssidrefs Off = %x.\n", ntohl(cwbuf->chwall_ssid_offset));
121 printf("Conflicts Off = %x.\n",
122 ntohl(cwbuf->chwall_conflict_sets_offset));
123 printf("Runing T. Off = %x.\n",
124 ntohl(cwbuf->chwall_running_types_offset));
125 printf("C. Agg. Off = %x.\n",
126 ntohl(cwbuf->chwall_conflict_aggregate_offset));
127 printf("\nSSID To CHWALL-Type matrix:\n");
129 ssids = (domaintype_t *) (buf + ntohl(cwbuf->chwall_ssid_offset));
130 for (i = 0; i < ntohl(cwbuf->chwall_max_ssidrefs); i++)
131 {
132 printf("\n ssidref%2x: ", i);
133 for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++)
134 printf("%02x ",
135 ntohs(ssids[i * ntohl(cwbuf->chwall_max_types) + j]));
136 }
137 printf("\n\nConfict Sets:\n");
138 conflicts =
139 (domaintype_t *) (buf + ntohl(cwbuf->chwall_conflict_sets_offset));
140 for (i = 0; i < ntohl(cwbuf->chwall_max_conflictsets); i++)
141 {
142 printf("\n c-set%2x: ", i);
143 for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++)
144 printf("%02x ",
145 ntohs(conflicts
146 [i * ntohl(cwbuf->chwall_max_types) + j]));
147 }
148 printf("\n");
150 printf("\nRunning\nTypes: ");
151 if (ntohl(cwbuf->chwall_running_types_offset))
152 {
153 running_types =
154 (domaintype_t *) (buf +
155 ntohl(cwbuf->chwall_running_types_offset));
156 for (i = 0; i < ntohl(cwbuf->chwall_max_types); i++)
157 {
158 printf("%02x ", ntohs(running_types[i]));
159 }
160 printf("\n");
161 } else {
162 printf("Not Reported!\n");
163 }
164 printf("\nConflict\nAggregate Set: ");
165 if (ntohl(cwbuf->chwall_conflict_aggregate_offset))
166 {
167 conflict_aggregate =
168 (domaintype_t *) (buf +
169 ntohl(cwbuf->chwall_conflict_aggregate_offset));
170 for (i = 0; i < ntohl(cwbuf->chwall_max_types); i++)
171 {
172 printf("%02x ", ntohs(conflict_aggregate[i]));
173 }
174 printf("\n\n");
175 } else {
176 printf("Not Reported!\n");
177 }
178 }
180 void acm_dump_ste_buffer(void *buf, int buflen)
181 {
183 struct acm_ste_policy_buffer *stebuf =
184 (struct acm_ste_policy_buffer *) buf;
185 domaintype_t *ssids;
186 int i, j;
189 if (ntohl(stebuf->policy_code) != ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
190 printf("SIMPLE TYPE ENFORCEMENT POLICY CODE not found ERROR!!\n");
191 return;
192 }
193 printf("\nSimple Type Enforcement policy:\n");
194 printf("===============================\n");
195 printf("Policy version= %x.\n", ntohl(stebuf->policy_version));
196 printf("Max Types = %x.\n", ntohl(stebuf->ste_max_types));
197 printf("Max Ssidrefs = %x.\n", ntohl(stebuf->ste_max_ssidrefs));
198 printf("Ssidrefs Off = %x.\n", ntohl(stebuf->ste_ssid_offset));
199 printf("\nSSID To STE-Type matrix:\n");
201 ssids = (domaintype_t *) (buf + ntohl(stebuf->ste_ssid_offset));
202 for (i = 0; i < ntohl(stebuf->ste_max_ssidrefs); i++)
203 {
204 printf("\n ssidref%2x: ", i);
205 for (j = 0; j < ntohl(stebuf->ste_max_types); j++)
206 printf("%02x ", ntohs(ssids[i * ntohl(stebuf->ste_max_types) + j]));
207 }
208 printf("\n\n");
209 }
211 void acm_dump_policy_buffer(void *buf, int buflen)
212 {
213 struct acm_policy_buffer *pol = (struct acm_policy_buffer *) buf;
215 printf("\nPolicy dump:\n");
216 printf("============\n");
217 printf("PolicyVer = %x.\n", ntohl(pol->policy_version));
218 printf("Magic = %x.\n", ntohl(pol->magic));
219 printf("Len = %x.\n", ntohl(pol->len));
220 printf("Primary = %s (c=%x, off=%x).\n",
221 ACM_POLICY_NAME(ntohl(pol->primary_policy_code)),
222 ntohl(pol->primary_policy_code),
223 ntohl(pol->primary_buffer_offset));
224 printf("Secondary = %s (c=%x, off=%x).\n",
225 ACM_POLICY_NAME(ntohl(pol->secondary_policy_code)),
226 ntohl(pol->secondary_policy_code),
227 ntohl(pol->secondary_buffer_offset));
228 switch (ntohl(pol->primary_policy_code))
229 {
230 case ACM_CHINESE_WALL_POLICY:
231 acm_dump_chinesewall_buffer(buf +
232 ntohl(pol->primary_buffer_offset),
233 ntohl(pol->len) -
234 ntohl(pol->primary_buffer_offset));
235 break;
237 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
238 acm_dump_ste_buffer(buf + ntohl(pol->primary_buffer_offset),
239 ntohl(pol->len) -
240 ntohl(pol->primary_buffer_offset));
241 break;
243 case ACM_NULL_POLICY:
244 printf("Primary policy is NULL Policy (n/a).\n");
245 break;
247 default:
248 printf("UNKNOWN POLICY!\n");
249 }
251 switch (ntohl(pol->secondary_policy_code))
252 {
253 case ACM_CHINESE_WALL_POLICY:
254 acm_dump_chinesewall_buffer(buf +
255 ntohl(pol->secondary_buffer_offset),
256 ntohl(pol->len) -
257 ntohl(pol->secondary_buffer_offset));
258 break;
260 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
261 acm_dump_ste_buffer(buf + ntohl(pol->secondary_buffer_offset),
262 ntohl(pol->len) -
263 ntohl(pol->secondary_buffer_offset));
264 break;
266 case ACM_NULL_POLICY:
267 printf("Secondary policy is NULL Policy (n/a).\n");
268 break;
270 default:
271 printf("UNKNOWN POLICY!\n");
272 }
273 }
275 /******************************* get policy ******************************/
277 #define PULL_CACHE_SIZE 8192
278 u8 pull_buffer[PULL_CACHE_SIZE];
279 int acm_domain_getpolicy(int xc_handle)
280 {
281 acm_op_t op;
282 int ret;
284 memset(pull_buffer, 0x00, sizeof(pull_buffer));
285 op.cmd = ACM_GETPOLICY;
286 op.interface_version = ACM_INTERFACE_VERSION;
287 op.u.getpolicy.pullcache = (void *) pull_buffer;
288 op.u.getpolicy.pullcache_size = sizeof(pull_buffer);
289 ret = do_acm_op(xc_handle, &op);
290 /* dump policy */
291 acm_dump_policy_buffer(pull_buffer, sizeof(pull_buffer));
292 return ret;
293 }
295 /************************ load binary policy ******************************/
297 int acm_domain_loadpolicy(int xc_handle, const char *filename)
298 {
299 struct stat mystat;
300 int ret, fd;
301 off_t len;
302 u8 *buffer;
304 if ((ret = stat(filename, &mystat)))
305 {
306 printf("File %s not found.\n", filename);
307 goto out;
308 }
310 len = mystat.st_size;
311 if ((buffer = malloc(len)) == NULL)
312 {
313 ret = -ENOMEM;
314 goto out;
315 }
316 if ((fd = open(filename, O_RDONLY)) <= 0)
317 {
318 ret = -ENOENT;
319 printf("File %s not found.\n", filename);
320 goto free_out;
321 }
322 if (len == read(fd, buffer, len))
323 {
324 acm_op_t op;
325 /* dump it and then push it down into xen/acm */
326 acm_dump_policy_buffer(buffer, len);
327 op.cmd = ACM_SETPOLICY;
328 op.interface_version = ACM_INTERFACE_VERSION;
329 op.u.setpolicy.pushcache = (void *) buffer;
330 op.u.setpolicy.pushcache_size = len;
331 ret = do_acm_op(xc_handle, &op);
333 if (ret)
334 printf
335 ("ERROR setting policy. Try 'xm dmesg' to see details.\n");
336 else
337 printf("Successfully changed policy.\n");
339 } else {
340 ret = -1;
341 }
342 close(fd);
343 free_out:
344 free(buffer);
345 out:
346 return ret;
347 }
349 /************************ dump hook statistics ******************************/
350 void dump_ste_stats(struct acm_ste_stats_buffer *ste_stats)
351 {
352 printf("STE-Policy Security Hook Statistics:\n");
353 printf("ste: event_channel eval_count = %d\n",
354 ntohl(ste_stats->ec_eval_count));
355 printf("ste: event_channel denied_count = %d\n",
356 ntohl(ste_stats->ec_denied_count));
357 printf("ste: event_channel cache_hit_count = %d\n",
358 ntohl(ste_stats->ec_cachehit_count));
359 printf("ste:\n");
360 printf("ste: grant_table eval_count = %d\n",
361 ntohl(ste_stats->gt_eval_count));
362 printf("ste: grant_table denied_count = %d\n",
363 ntohl(ste_stats->gt_denied_count));
364 printf("ste: grant_table cache_hit_count = %d\n",
365 ntohl(ste_stats->gt_cachehit_count));
366 }
368 #define PULL_STATS_SIZE 8192
369 int acm_domain_dumpstats(int xc_handle)
370 {
371 u8 stats_buffer[PULL_STATS_SIZE];
372 acm_op_t op;
373 int ret;
374 struct acm_stats_buffer *stats;
376 memset(stats_buffer, 0x00, sizeof(stats_buffer));
377 op.cmd = ACM_DUMPSTATS;
378 op.interface_version = ACM_INTERFACE_VERSION;
379 op.u.dumpstats.pullcache = (void *) stats_buffer;
380 op.u.dumpstats.pullcache_size = sizeof(stats_buffer);
381 ret = do_acm_op(xc_handle, &op);
383 if (ret < 0)
384 {
385 printf("ERROR dumping policy stats. Try 'xm dmesg' to see details.\n");
386 return ret;
387 }
388 stats = (struct acm_stats_buffer *) stats_buffer;
390 printf("\nPolicy dump:\n");
391 printf("============\n");
392 printf("Magic = %x.\n", ntohl(stats->magic));
393 printf("Len = %x.\n", ntohl(stats->len));
395 switch (ntohl(stats->primary_policy_code))
396 {
397 case ACM_NULL_POLICY:
398 printf("NULL Policy: No statistics apply.\n");
399 break;
401 case ACM_CHINESE_WALL_POLICY:
402 printf("Chinese Wall Policy: No statistics apply.\n");
403 break;
405 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
406 dump_ste_stats((struct acm_ste_stats_buffer *) (stats_buffer +
407 ntohl(stats->
408 primary_stats_offset)));
409 break;
411 default:
412 printf("UNKNOWN PRIMARY POLICY ERROR!\n");
413 }
415 switch (ntohl(stats->secondary_policy_code))
416 {
417 case ACM_NULL_POLICY:
418 printf("NULL Policy: No statistics apply.\n");
419 break;
421 case ACM_CHINESE_WALL_POLICY:
422 printf("Chinese Wall Policy: No statistics apply.\n");
423 break;
425 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
426 dump_ste_stats((struct acm_ste_stats_buffer *) (stats_buffer +
427 ntohl(stats->
428 secondary_stats_offset)));
429 break;
431 default:
432 printf("UNKNOWN SECONDARY POLICY ERROR!\n");
433 }
434 return ret;
435 }
436 /************************ get ssidref & types ******************************/
437 /*
438 * the ssid (types) can be looked up either by domain id or by ssidref
439 */
440 int acm_domain_getssid(int xc_handle, int argc, char * const argv[])
441 {
442 /* this includes header and a set of types */
443 #define MAX_SSIDBUFFER 2000
444 int ret, i;
445 acm_op_t op;
446 struct acm_ssid_buffer *hdr;
447 unsigned char *buf;
448 int nice_print = 1;
450 op.cmd = ACM_GETSSID;
451 op.interface_version = ACM_INTERFACE_VERSION;
452 op.u.getssid.get_ssid_by = UNSET;
453 /* arguments
454 -d ... domain id to look up
455 -s ... ssidref number to look up
456 -f ... formatted print (scripts depend on this format)
457 */
458 while (1)
459 {
460 int c = getopt(argc, argv, "d:s:f");
461 if (c == -1)
462 break;
463 if (c == 'd')
464 {
465 if (op.u.getssid.get_ssid_by != UNSET)
466 usage(argv[0]);
467 op.u.getssid.get_ssid_by = DOMAINID;
468 op.u.getssid.id.domainid = strtoul(optarg, NULL, 0);
469 }
470 else if (c== 's')
471 {
472 if (op.u.getssid.get_ssid_by != UNSET)
473 usage(argv[0]);
474 op.u.getssid.get_ssid_by = SSIDREF;
475 op.u.getssid.id.ssidref = strtoul(optarg, NULL, 0);
476 }
477 else if (c== 'f')
478 {
479 nice_print = 0;
480 }
481 else
482 usage(argv[0]);
483 }
484 if (op.u.getssid.get_ssid_by == UNSET)
485 usage(argv[0]);
487 buf = malloc(MAX_SSIDBUFFER);
488 if (!buf)
489 return -ENOMEM;
491 /* dump it and then push it down into xen/acm */
492 op.u.getssid.ssidbuf = buf; /* out */
493 op.u.getssid.ssidbuf_size = MAX_SSIDBUFFER;
494 ret = do_acm_op(xc_handle, &op);
496 if (ret)
497 {
498 printf("ERROR getting ssidref. Try 'xm dmesg' to see details.\n");
499 goto out;
500 }
501 hdr = (struct acm_ssid_buffer *)buf;
502 if (hdr->len > MAX_SSIDBUFFER)
503 {
504 printf("ERROR: Buffer length inconsistent (ret=%d, hdr->len=%d)!\n",
505 ret, hdr->len);
506 return -EIO;
507 }
508 if (nice_print)
509 {
510 printf("SSID: ssidref = 0x%08x \n", hdr->ssidref);
511 printf(" P: %s, max_types = %d\n",
512 ACM_POLICY_NAME(hdr->primary_policy_code), hdr->primary_max_types);
513 printf(" Types: ");
514 for (i=0; i< hdr->primary_max_types; i++)
515 if (buf[hdr->primary_types_offset + i])
516 printf("%02x ", i);
517 else
518 printf("-- ");
519 printf("\n");
521 printf(" S: %s, max_types = %d\n",
522 ACM_POLICY_NAME(hdr->secondary_policy_code), hdr->secondary_max_types);
523 printf(" Types: ");
524 for (i=0; i< hdr->secondary_max_types; i++)
525 if (buf[hdr->secondary_types_offset + i])
526 printf("%02x ", i);
527 else
528 printf("-- ");
529 printf("\n");
530 }
531 else
532 {
533 /* formatted print for use with scripts (.sh)
534 * update scripts when updating here (usually
535 * used in combination with -d to determine a
536 * running domain's label
537 */
538 printf("SSID: ssidref = 0x%08x \n", hdr->ssidref);
539 }
541 /* return ste ssidref */
542 if (hdr->primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
543 ret = (hdr->ssidref) & 0xffff;
544 else if (hdr->secondary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
545 ret = (hdr->ssidref) >> 16;
546 out:
547 return ret;
548 }
550 /***************************** main **************************************/
552 int main(int argc, char **argv)
553 {
555 int acm_cmd_fd, ret = 0;
557 if (argc < 2)
558 usage(argv[0]);
560 if ((acm_cmd_fd = open("/proc/xen/privcmd", O_RDONLY)) <= 0)
561 {
562 printf("ERROR: Could not open xen privcmd device!\n");
563 exit(-1);
564 }
566 if (!strcmp(argv[1], "getpolicy")) {
567 if (argc != 2)
568 usage(argv[0]);
569 ret = acm_domain_getpolicy(acm_cmd_fd);
570 } else if (!strcmp(argv[1], "loadpolicy")) {
571 if (argc != 3)
572 usage(argv[0]);
573 ret = acm_domain_loadpolicy(acm_cmd_fd, argv[2]);
574 } else if (!strcmp(argv[1], "dumpstats")) {
575 if (argc != 2)
576 usage(argv[0]);
577 ret = acm_domain_dumpstats(acm_cmd_fd);
578 } else if (!strcmp(argv[1], "getssid")) {
579 ret = acm_domain_getssid(acm_cmd_fd, argc, argv);
580 } else
581 usage(argv[0]);
583 close(acm_cmd_fd);
584 return ret;
585 }