mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
in secpol_tool. Signed-off-by: Jerone Young <jyoung5@us.ibm.com>
649 lines
21 KiB
C
649 lines
21 KiB
C
/****************************************************************
|
|
* secpol_tool.c
|
|
*
|
|
* Copyright (C) 2005 IBM Corporation
|
|
*
|
|
* Authors:
|
|
* Reiner Sailer <sailer@watson.ibm.com>
|
|
* Stefan Berger <stefanb@watson.ibm.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation, version 2 of the
|
|
* License.
|
|
*
|
|
* sHype policy management tool. This code runs in a domain and
|
|
* manages the Xen security policy by interacting with the
|
|
* Xen access control module via a /proc/xen/privcmd proc-ioctl,
|
|
* which is translated into a acm_op hypercall into Xen.
|
|
*
|
|
* indent -i4 -kr -nut
|
|
*/
|
|
|
|
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <stdlib.h>
|
|
#include <sys/ioctl.h>
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
#include <netinet/in.h>
|
|
|
|
typedef uint8_t u8;
|
|
typedef uint16_t u16;
|
|
typedef uint32_t u32;
|
|
typedef uint64_t u64;
|
|
typedef int8_t s8;
|
|
typedef int16_t s16;
|
|
typedef int32_t s32;
|
|
typedef int64_t s64;
|
|
|
|
#include <xen/acm.h>
|
|
#include <xen/acm_ops.h>
|
|
#include <xen/linux/privcmd.h>
|
|
|
|
#define PERROR(_m, _a...) \
|
|
fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
|
|
errno, strerror(errno))
|
|
|
|
static inline int do_policycmd(int xc_handle, unsigned int cmd,
|
|
unsigned long data)
|
|
{
|
|
return ioctl(xc_handle, cmd, data);
|
|
}
|
|
|
|
static inline int do_xen_hypercall(int xc_handle,
|
|
privcmd_hypercall_t * hypercall)
|
|
{
|
|
return do_policycmd(xc_handle,
|
|
IOCTL_PRIVCMD_HYPERCALL,
|
|
(unsigned long) hypercall);
|
|
}
|
|
|
|
static inline int do_acm_op(int xc_handle, acm_op_t * op)
|
|
{
|
|
int ret = -1;
|
|
privcmd_hypercall_t hypercall;
|
|
|
|
op->interface_version = ACM_INTERFACE_VERSION;
|
|
|
|
hypercall.op = __HYPERVISOR_acm_op;
|
|
hypercall.arg[0] = (unsigned long) op;
|
|
|
|
if (mlock(op, sizeof(*op)) != 0)
|
|
{
|
|
PERROR("Could not lock memory for Xen policy hypercall");
|
|
goto out1;
|
|
}
|
|
|
|
if ((ret = do_xen_hypercall(xc_handle, &hypercall)) < 0)
|
|
{
|
|
if (errno == EACCES)
|
|
fprintf(stderr, "ACM operation failed -- need to"
|
|
" rebuild the user-space tool set?\n");
|
|
goto out2;
|
|
}
|
|
|
|
out2:(void) munlock(op, sizeof(*op));
|
|
out1:return ret;
|
|
}
|
|
|
|
/*************************** DUMPS *******************************/
|
|
|
|
void acm_dump_chinesewall_buffer(void *buf, int buflen)
|
|
{
|
|
|
|
struct acm_chwall_policy_buffer *cwbuf =
|
|
(struct acm_chwall_policy_buffer *) buf;
|
|
domaintype_t *ssids, *conflicts, *running_types, *conflict_aggregate;
|
|
int i, j;
|
|
|
|
|
|
if (htonl(cwbuf->policy_code) != ACM_CHINESE_WALL_POLICY)
|
|
{
|
|
printf("CHINESE WALL POLICY CODE not found ERROR!!\n");
|
|
return;
|
|
}
|
|
printf("\n\nChinese Wall policy:\n");
|
|
printf("====================\n");
|
|
printf("Policy version= %x.\n", ntohl(cwbuf->policy_version));
|
|
printf("Max Types = %x.\n", ntohl(cwbuf->chwall_max_types));
|
|
printf("Max Ssidrefs = %x.\n", ntohl(cwbuf->chwall_max_ssidrefs));
|
|
printf("Max ConfSets = %x.\n", ntohl(cwbuf->chwall_max_conflictsets));
|
|
printf("Ssidrefs Off = %x.\n", ntohl(cwbuf->chwall_ssid_offset));
|
|
printf("Conflicts Off = %x.\n",
|
|
ntohl(cwbuf->chwall_conflict_sets_offset));
|
|
printf("Runing T. Off = %x.\n",
|
|
ntohl(cwbuf->chwall_running_types_offset));
|
|
printf("C. Agg. Off = %x.\n",
|
|
ntohl(cwbuf->chwall_conflict_aggregate_offset));
|
|
printf("\nSSID To CHWALL-Type matrix:\n");
|
|
|
|
ssids = (domaintype_t *) (buf + ntohl(cwbuf->chwall_ssid_offset));
|
|
for (i = 0; i < ntohl(cwbuf->chwall_max_ssidrefs); i++)
|
|
{
|
|
printf("\n ssidref%2x: ", i);
|
|
for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++)
|
|
printf("%02x ",
|
|
ntohs(ssids[i * ntohl(cwbuf->chwall_max_types) + j]));
|
|
}
|
|
printf("\n\nConfict Sets:\n");
|
|
conflicts =
|
|
(domaintype_t *) (buf + ntohl(cwbuf->chwall_conflict_sets_offset));
|
|
for (i = 0; i < ntohl(cwbuf->chwall_max_conflictsets); i++)
|
|
{
|
|
printf("\n c-set%2x: ", i);
|
|
for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++)
|
|
printf("%02x ",
|
|
ntohs(conflicts
|
|
[i * ntohl(cwbuf->chwall_max_types) + j]));
|
|
}
|
|
printf("\n");
|
|
|
|
printf("\nRunning\nTypes: ");
|
|
if (ntohl(cwbuf->chwall_running_types_offset))
|
|
{
|
|
running_types =
|
|
(domaintype_t *) (buf +
|
|
ntohl(cwbuf->chwall_running_types_offset));
|
|
for (i = 0; i < ntohl(cwbuf->chwall_max_types); i++)
|
|
{
|
|
printf("%02x ", ntohs(running_types[i]));
|
|
}
|
|
printf("\n");
|
|
} else {
|
|
printf("Not Reported!\n");
|
|
}
|
|
printf("\nConflict\nAggregate Set: ");
|
|
if (ntohl(cwbuf->chwall_conflict_aggregate_offset))
|
|
{
|
|
conflict_aggregate =
|
|
(domaintype_t *) (buf +
|
|
ntohl(cwbuf->chwall_conflict_aggregate_offset));
|
|
for (i = 0; i < ntohl(cwbuf->chwall_max_types); i++)
|
|
{
|
|
printf("%02x ", ntohs(conflict_aggregate[i]));
|
|
}
|
|
printf("\n\n");
|
|
} else {
|
|
printf("Not Reported!\n");
|
|
}
|
|
}
|
|
|
|
void acm_dump_ste_buffer(void *buf, int buflen)
|
|
{
|
|
|
|
struct acm_ste_policy_buffer *stebuf =
|
|
(struct acm_ste_policy_buffer *) buf;
|
|
domaintype_t *ssids;
|
|
int i, j;
|
|
|
|
|
|
if (ntohl(stebuf->policy_code) != ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
|
|
printf("SIMPLE TYPE ENFORCEMENT POLICY CODE not found ERROR!!\n");
|
|
return;
|
|
}
|
|
printf("\nSimple Type Enforcement policy:\n");
|
|
printf("===============================\n");
|
|
printf("Policy version= %x.\n", ntohl(stebuf->policy_version));
|
|
printf("Max Types = %x.\n", ntohl(stebuf->ste_max_types));
|
|
printf("Max Ssidrefs = %x.\n", ntohl(stebuf->ste_max_ssidrefs));
|
|
printf("Ssidrefs Off = %x.\n", ntohl(stebuf->ste_ssid_offset));
|
|
printf("\nSSID To STE-Type matrix:\n");
|
|
|
|
ssids = (domaintype_t *) (buf + ntohl(stebuf->ste_ssid_offset));
|
|
for (i = 0; i < ntohl(stebuf->ste_max_ssidrefs); i++)
|
|
{
|
|
printf("\n ssidref%2x: ", i);
|
|
for (j = 0; j < ntohl(stebuf->ste_max_types); j++)
|
|
printf("%02x ", ntohs(ssids[i * ntohl(stebuf->ste_max_types) + j]));
|
|
}
|
|
printf("\n\n");
|
|
}
|
|
|
|
void acm_dump_policy_buffer(void *buf, int buflen)
|
|
{
|
|
struct acm_policy_buffer *pol = (struct acm_policy_buffer *) buf;
|
|
|
|
printf("\nPolicy dump:\n");
|
|
printf("============\n");
|
|
printf("PolicyVer = %x.\n", ntohl(pol->policy_version));
|
|
printf("Magic = %x.\n", ntohl(pol->magic));
|
|
printf("Len = %x.\n", ntohl(pol->len));
|
|
printf("Primary = %s (c=%x, off=%x).\n",
|
|
ACM_POLICY_NAME(ntohl(pol->primary_policy_code)),
|
|
ntohl(pol->primary_policy_code),
|
|
ntohl(pol->primary_buffer_offset));
|
|
printf("Secondary = %s (c=%x, off=%x).\n",
|
|
ACM_POLICY_NAME(ntohl(pol->secondary_policy_code)),
|
|
ntohl(pol->secondary_policy_code),
|
|
ntohl(pol->secondary_buffer_offset));
|
|
switch (ntohl(pol->primary_policy_code))
|
|
{
|
|
case ACM_CHINESE_WALL_POLICY:
|
|
acm_dump_chinesewall_buffer(buf +
|
|
ntohl(pol->primary_buffer_offset),
|
|
ntohl(pol->len) -
|
|
ntohl(pol->primary_buffer_offset));
|
|
break;
|
|
|
|
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
|
|
acm_dump_ste_buffer(buf + ntohl(pol->primary_buffer_offset),
|
|
ntohl(pol->len) -
|
|
ntohl(pol->primary_buffer_offset));
|
|
break;
|
|
|
|
case ACM_NULL_POLICY:
|
|
printf("Primary policy is NULL Policy (n/a).\n");
|
|
break;
|
|
|
|
default:
|
|
printf("UNKNOWN POLICY!\n");
|
|
}
|
|
|
|
switch (ntohl(pol->secondary_policy_code))
|
|
{
|
|
case ACM_CHINESE_WALL_POLICY:
|
|
acm_dump_chinesewall_buffer(buf +
|
|
ntohl(pol->secondary_buffer_offset),
|
|
ntohl(pol->len) -
|
|
ntohl(pol->secondary_buffer_offset));
|
|
break;
|
|
|
|
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
|
|
acm_dump_ste_buffer(buf + ntohl(pol->secondary_buffer_offset),
|
|
ntohl(pol->len) -
|
|
ntohl(pol->secondary_buffer_offset));
|
|
break;
|
|
|
|
case ACM_NULL_POLICY:
|
|
printf("Secondary policy is NULL Policy (n/a).\n");
|
|
break;
|
|
|
|
default:
|
|
printf("UNKNOWN POLICY!\n");
|
|
}
|
|
}
|
|
|
|
/*************************** set policy ****************************/
|
|
|
|
int acm_domain_set_chwallpolicy(void *bufstart, int buflen)
|
|
{
|
|
#define CWALL_MAX_SSIDREFS 6
|
|
#define CWALL_MAX_TYPES 10
|
|
#define CWALL_MAX_CONFLICTSETS 2
|
|
|
|
struct acm_chwall_policy_buffer *chwall_bin_pol =
|
|
(struct acm_chwall_policy_buffer *) bufstart;
|
|
domaintype_t *ssidrefs, *conflicts;
|
|
int ret = 0;
|
|
int j;
|
|
|
|
chwall_bin_pol->chwall_max_types = htonl(CWALL_MAX_TYPES);
|
|
chwall_bin_pol->chwall_max_ssidrefs = htonl(CWALL_MAX_SSIDREFS);
|
|
chwall_bin_pol->policy_code = htonl(ACM_CHINESE_WALL_POLICY);
|
|
chwall_bin_pol->policy_version = htonl(ACM_CHWALL_VERSION);
|
|
chwall_bin_pol->chwall_ssid_offset =
|
|
htonl(sizeof(struct acm_chwall_policy_buffer));
|
|
chwall_bin_pol->chwall_max_conflictsets =
|
|
htonl(CWALL_MAX_CONFLICTSETS);
|
|
chwall_bin_pol->chwall_conflict_sets_offset =
|
|
htonl(ntohl(chwall_bin_pol->chwall_ssid_offset) +
|
|
sizeof(domaintype_t) * CWALL_MAX_SSIDREFS * CWALL_MAX_TYPES);
|
|
chwall_bin_pol->chwall_running_types_offset = 0; /* not set */
|
|
chwall_bin_pol->chwall_conflict_aggregate_offset = 0; /* not set */
|
|
ret += sizeof(struct acm_chwall_policy_buffer);
|
|
/* now push example ssids into the buffer (max_ssidrefs x max_types entries) */
|
|
/* check buffer size */
|
|
if ((buflen - ret) <
|
|
(CWALL_MAX_TYPES * CWALL_MAX_SSIDREFS * sizeof(domaintype_t)))
|
|
return -1; /* not enough space */
|
|
|
|
ssidrefs = (domaintype_t *) (bufstart +
|
|
ntohl(chwall_bin_pol->chwall_ssid_offset));
|
|
memset(ssidrefs, 0,
|
|
CWALL_MAX_TYPES * CWALL_MAX_SSIDREFS * sizeof(domaintype_t));
|
|
|
|
/* now set type j-1 for ssidref i+1 */
|
|
for (j = 0; j <= CWALL_MAX_SSIDREFS; j++)
|
|
if ((0 < j) && (j <= CWALL_MAX_TYPES))
|
|
ssidrefs[j * CWALL_MAX_TYPES + j - 1] = htons(1);
|
|
|
|
ret += CWALL_MAX_TYPES * CWALL_MAX_SSIDREFS * sizeof(domaintype_t);
|
|
if ((buflen - ret) <
|
|
(CWALL_MAX_CONFLICTSETS * CWALL_MAX_TYPES * sizeof(domaintype_t)))
|
|
return -1; /* not enough space */
|
|
|
|
/* now the chinese wall policy conflict sets */
|
|
conflicts = (domaintype_t *) (bufstart +
|
|
ntohl(chwall_bin_pol->
|
|
chwall_conflict_sets_offset));
|
|
memset((void *) conflicts, 0,
|
|
CWALL_MAX_CONFLICTSETS * CWALL_MAX_TYPES *
|
|
sizeof(domaintype_t));
|
|
/* just 1 conflict set [0]={2,3}, [1]={1,5,6} */
|
|
if (CWALL_MAX_TYPES > 3)
|
|
{
|
|
conflicts[2] = htons(1);
|
|
conflicts[3] = htons(1); /* {2,3} */
|
|
conflicts[CWALL_MAX_TYPES + 1] = htons(1);
|
|
conflicts[CWALL_MAX_TYPES + 5] = htons(1);
|
|
conflicts[CWALL_MAX_TYPES + 6] = htons(1); /* {0,5,6} */
|
|
}
|
|
ret += sizeof(domaintype_t) * CWALL_MAX_CONFLICTSETS * CWALL_MAX_TYPES;
|
|
return ret;
|
|
}
|
|
|
|
int acm_domain_set_stepolicy(void *bufstart, int buflen)
|
|
{
|
|
#define STE_MAX_SSIDREFS 6
|
|
#define STE_MAX_TYPES 5
|
|
|
|
struct acm_ste_policy_buffer *ste_bin_pol =
|
|
(struct acm_ste_policy_buffer *) bufstart;
|
|
domaintype_t *ssidrefs;
|
|
int j, ret = 0;
|
|
|
|
ste_bin_pol->ste_max_types = htonl(STE_MAX_TYPES);
|
|
ste_bin_pol->ste_max_ssidrefs = htonl(STE_MAX_SSIDREFS);
|
|
ste_bin_pol->policy_code = htonl(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
|
|
ste_bin_pol->policy_version = htonl(ACM_STE_VERSION);
|
|
ste_bin_pol->ste_ssid_offset =
|
|
htonl(sizeof(struct acm_ste_policy_buffer));
|
|
ret += sizeof(struct acm_ste_policy_buffer);
|
|
/* check buffer size */
|
|
if ((buflen - ret) <
|
|
(STE_MAX_TYPES * STE_MAX_SSIDREFS * sizeof(domaintype_t)))
|
|
return -1; /* not enough space */
|
|
|
|
ssidrefs =
|
|
(domaintype_t *) (bufstart + ntohl(ste_bin_pol->ste_ssid_offset));
|
|
memset(ssidrefs, 0,
|
|
STE_MAX_TYPES * STE_MAX_SSIDREFS * sizeof(domaintype_t));
|
|
/* all types 1 for ssidref 1 */
|
|
for (j = 0; j < STE_MAX_TYPES; j++)
|
|
ssidrefs[1 * STE_MAX_TYPES + j] = htons(1);
|
|
/* now set type j-1 for ssidref j */
|
|
for (j = 0; j < STE_MAX_SSIDREFS; j++)
|
|
if ((0 < j) && (j <= STE_MAX_TYPES))
|
|
ssidrefs[j * STE_MAX_TYPES + j - 1] = htons(1);
|
|
ret += STE_MAX_TYPES * STE_MAX_SSIDREFS * sizeof(domaintype_t);
|
|
return ret;
|
|
}
|
|
|
|
#define MAX_PUSH_BUFFER 16384
|
|
u8 push_buffer[MAX_PUSH_BUFFER];
|
|
|
|
int acm_domain_setpolicy(int xc_handle)
|
|
{
|
|
int ret;
|
|
struct acm_policy_buffer *bin_pol;
|
|
acm_op_t op;
|
|
|
|
/* future: read policy from file and set it */
|
|
bin_pol = (struct acm_policy_buffer *) push_buffer;
|
|
bin_pol->policy_version = htonl(ACM_POLICY_VERSION);
|
|
bin_pol->magic = htonl(ACM_MAGIC);
|
|
bin_pol->primary_policy_code = htonl(ACM_CHINESE_WALL_POLICY);
|
|
bin_pol->secondary_policy_code =
|
|
htonl(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
|
|
|
|
bin_pol->len = htonl(sizeof(struct acm_policy_buffer));
|
|
bin_pol->primary_buffer_offset = htonl(ntohl(bin_pol->len));
|
|
ret =
|
|
acm_domain_set_chwallpolicy(push_buffer +
|
|
ntohl(bin_pol->primary_buffer_offset),
|
|
MAX_PUSH_BUFFER -
|
|
ntohl(bin_pol->primary_buffer_offset));
|
|
if (ret < 0)
|
|
{
|
|
printf("ERROR creating chwallpolicy buffer.\n");
|
|
return -1;
|
|
}
|
|
bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
|
|
bin_pol->secondary_buffer_offset = htonl(ntohl(bin_pol->len));
|
|
ret = acm_domain_set_stepolicy(push_buffer +
|
|
ntohl(bin_pol->secondary_buffer_offset),
|
|
MAX_PUSH_BUFFER -
|
|
ntohl(bin_pol->secondary_buffer_offset));
|
|
if (ret < 0)
|
|
{
|
|
printf("ERROR creating chwallpolicy buffer.\n");
|
|
return -1;
|
|
}
|
|
bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
|
|
|
|
/* dump it and then push it down into xen/acm */
|
|
acm_dump_policy_buffer(push_buffer, ntohl(bin_pol->len));
|
|
|
|
op.cmd = ACM_SETPOLICY;
|
|
op.interface_version = ACM_INTERFACE_VERSION;
|
|
op.u.setpolicy.pushcache = (void *) push_buffer;
|
|
op.u.setpolicy.pushcache_size = ntohl(bin_pol->len);
|
|
ret = do_acm_op(xc_handle, &op);
|
|
|
|
if (ret)
|
|
printf("ERROR setting policy. Use 'xm dmesg' to see details.\n");
|
|
else
|
|
printf("Successfully changed policy.\n");
|
|
|
|
return ret;
|
|
}
|
|
|
|
/******************************* get policy ******************************/
|
|
|
|
#define PULL_CACHE_SIZE 8192
|
|
u8 pull_buffer[PULL_CACHE_SIZE];
|
|
int acm_domain_getpolicy(int xc_handle)
|
|
{
|
|
acm_op_t op;
|
|
int ret;
|
|
|
|
memset(pull_buffer, 0x00, sizeof(pull_buffer));
|
|
op.cmd = ACM_GETPOLICY;
|
|
op.interface_version = ACM_INTERFACE_VERSION;
|
|
op.u.getpolicy.pullcache = (void *) pull_buffer;
|
|
op.u.getpolicy.pullcache_size = sizeof(pull_buffer);
|
|
ret = do_acm_op(xc_handle, &op);
|
|
/* dump policy */
|
|
acm_dump_policy_buffer(pull_buffer, sizeof(pull_buffer));
|
|
return ret;
|
|
}
|
|
|
|
/************************ load binary policy ******************************/
|
|
|
|
int acm_domain_loadpolicy(int xc_handle, const char *filename)
|
|
{
|
|
struct stat mystat;
|
|
int ret, fd;
|
|
off_t len;
|
|
u8 *buffer;
|
|
|
|
if ((ret = stat(filename, &mystat)))
|
|
{
|
|
printf("File %s not found.\n", filename);
|
|
goto out;
|
|
}
|
|
|
|
len = mystat.st_size;
|
|
if ((buffer = malloc(len)) == NULL)
|
|
{
|
|
ret = -ENOMEM;
|
|
goto out;
|
|
}
|
|
if ((fd = open(filename, O_RDONLY)) <= 0)
|
|
{
|
|
ret = -ENOENT;
|
|
printf("File %s not found.\n", filename);
|
|
goto free_out;
|
|
}
|
|
if (len == read(fd, buffer, len))
|
|
{
|
|
acm_op_t op;
|
|
/* dump it and then push it down into xen/acm */
|
|
acm_dump_policy_buffer(buffer, len);
|
|
op.cmd = ACM_SETPOLICY;
|
|
op.interface_version = ACM_INTERFACE_VERSION;
|
|
op.u.setpolicy.pushcache = (void *) buffer;
|
|
op.u.setpolicy.pushcache_size = len;
|
|
ret = do_acm_op(xc_handle, &op);
|
|
|
|
if (ret)
|
|
printf
|
|
("ERROR setting policy. Use 'xm dmesg' to see details.\n");
|
|
else
|
|
printf("Successfully changed policy.\n");
|
|
|
|
} else {
|
|
ret = -1;
|
|
}
|
|
close(fd);
|
|
free_out:
|
|
free(buffer);
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
/************************ dump hook statistics ******************************/
|
|
void dump_ste_stats(struct acm_ste_stats_buffer *ste_stats)
|
|
{
|
|
printf("STE-Policy Security Hook Statistics:\n");
|
|
printf("ste: event_channel eval_count = %d\n",
|
|
ntohl(ste_stats->ec_eval_count));
|
|
printf("ste: event_channel denied_count = %d\n",
|
|
ntohl(ste_stats->ec_denied_count));
|
|
printf("ste: event_channel cache_hit_count = %d\n",
|
|
ntohl(ste_stats->ec_cachehit_count));
|
|
printf("ste:\n");
|
|
printf("ste: grant_table eval_count = %d\n",
|
|
ntohl(ste_stats->gt_eval_count));
|
|
printf("ste: grant_table denied_count = %d\n",
|
|
ntohl(ste_stats->gt_denied_count));
|
|
printf("ste: grant_table cache_hit_count = %d\n",
|
|
ntohl(ste_stats->gt_cachehit_count));
|
|
}
|
|
|
|
#define PULL_STATS_SIZE 8192
|
|
int acm_domain_dumpstats(int xc_handle)
|
|
{
|
|
u8 stats_buffer[PULL_STATS_SIZE];
|
|
acm_op_t op;
|
|
int ret;
|
|
struct acm_stats_buffer *stats;
|
|
|
|
memset(stats_buffer, 0x00, sizeof(stats_buffer));
|
|
op.cmd = ACM_DUMPSTATS;
|
|
op.interface_version = ACM_INTERFACE_VERSION;
|
|
op.u.dumpstats.pullcache = (void *) stats_buffer;
|
|
op.u.dumpstats.pullcache_size = sizeof(stats_buffer);
|
|
ret = do_acm_op(xc_handle, &op);
|
|
|
|
if (ret < 0)
|
|
{
|
|
printf("ERROR dumping policy stats. Use 'xm dmesg' to see details.\n");
|
|
return ret;
|
|
}
|
|
stats = (struct acm_stats_buffer *) stats_buffer;
|
|
|
|
printf("\nPolicy dump:\n");
|
|
printf("============\n");
|
|
printf("Magic = %x.\n", ntohl(stats->magic));
|
|
printf("Len = %x.\n", ntohl(stats->len));
|
|
|
|
switch (ntohl(stats->primary_policy_code))
|
|
{
|
|
case ACM_NULL_POLICY:
|
|
printf("NULL Policy: No statistics apply.\n");
|
|
break;
|
|
|
|
case ACM_CHINESE_WALL_POLICY:
|
|
printf("Chinese Wall Policy: No statistics apply.\n");
|
|
break;
|
|
|
|
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
|
|
dump_ste_stats((struct acm_ste_stats_buffer *) (stats_buffer +
|
|
ntohl(stats->
|
|
primary_stats_offset)));
|
|
break;
|
|
|
|
default:
|
|
printf("UNKNOWN PRIMARY POLICY ERROR!\n");
|
|
}
|
|
|
|
switch (ntohl(stats->secondary_policy_code))
|
|
{
|
|
case ACM_NULL_POLICY:
|
|
printf("NULL Policy: No statistics apply.\n");
|
|
break;
|
|
|
|
case ACM_CHINESE_WALL_POLICY:
|
|
printf("Chinese Wall Policy: No statistics apply.\n");
|
|
break;
|
|
|
|
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
|
|
dump_ste_stats((struct acm_ste_stats_buffer *) (stats_buffer +
|
|
ntohl(stats->
|
|
secondary_stats_offset)));
|
|
break;
|
|
|
|
default:
|
|
printf("UNKNOWN SECONDARY POLICY ERROR!\n");
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/***************************** main **************************************/
|
|
|
|
void usage(char *progname)
|
|
{
|
|
printf("Use: %s \n"
|
|
"\t setpolicy\n"
|
|
"\t getpolicy\n"
|
|
"\t dumpstats\n"
|
|
"\t loadpolicy <binary policy file>\n", progname);
|
|
exit(-1);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
|
|
int acm_cmd_fd, ret = 0;
|
|
|
|
if (argc < 2)
|
|
usage(argv[0]);
|
|
|
|
if ((acm_cmd_fd = open("/proc/xen/privcmd", O_RDONLY)) <= 0)
|
|
{
|
|
printf("ERROR: Could not open xen privcmd device!\n");
|
|
exit(-1);
|
|
}
|
|
|
|
if (!strcmp(argv[1], "setpolicy"))
|
|
{
|
|
if (argc != 2)
|
|
usage(argv[0]);
|
|
ret = acm_domain_setpolicy(acm_cmd_fd);
|
|
} else if (!strcmp(argv[1], "getpolicy")) {
|
|
if (argc != 2)
|
|
usage(argv[0]);
|
|
ret = acm_domain_getpolicy(acm_cmd_fd);
|
|
} else if (!strcmp(argv[1], "loadpolicy")) {
|
|
if (argc != 3)
|
|
usage(argv[0]);
|
|
ret = acm_domain_loadpolicy(acm_cmd_fd, argv[2]);
|
|
} else if (!strcmp(argv[1], "dumpstats")) {
|
|
if (argc != 2)
|
|
usage(argv[0]);
|
|
ret = acm_domain_dumpstats(acm_cmd_fd);
|
|
} else
|
|
usage(argv[0]);
|
|
|
|
close(acm_cmd_fd);
|
|
return ret;
|
|
}
|