Files
xen/tools/security/get_decision.c
T
kaf24@firebug.cl.cam.ac.uk cc677c9d4e This patch to the Xen access control module (ACM) and tools:
1. adapts ACM hooks to the slightly changed event channel structure
  2. introduces an ACM_GETDECISION command, which enables authorized 
domains to retrieve policy decisions regarding the sharing of resources 
(STE policy) from the Xen hypervisor
  3. includes cleanup (warnings I found when applying  analysis tools such 
as beam or flawfinder to the ACM code)

 The get_decision function is useful to enforce:
   *  the security policy on network traffic  in the network backends in 
domain 0; currently there is no enforcement in Dom0 and all packets flow 
freely
   *  the security policy in block device backends to control which 
domains can access which vdisk resources

I have added a small test program that shows how to use the get_decision 
ACM interface call, it is in tools/security/get_decision.c and will be 
compiled together with the policy tools. As usual, the ACM is unconfigured 
until you switch on a security policy on in Config.mk.

Signed-off: Reiner Sailer <sailer@us.ibm.com>
2005-10-20 21:37:15 +01:00

177 lines
5.4 KiB
C

/****************************************************************
* get_decision.c
*
* Copyright (C) 2005 IBM Corporation
*
* Authors:
* Reiner Sailer <sailer@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.
*
* An example program that shows how to retrieve an access control
* decision from the hypervisor ACM based on the currently active policy.
*
*/
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <string.h>
#include <netinet/in.h>
#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))
void usage(char *progname)
{
printf("Use: %s \n", progname);
printf(" Test program illustrating the retrieval of\n");
printf(" access control decisions from xen. At this time,\n");
printf(" only sharing (STE) policy decisions are supported.\n");
printf(" parameter options:\n");
printf("\t -i domid -i domid\n");
printf("\t -i domid -s ssidref\n");
printf("\t -s ssidref -s ssidref\n\n");
exit(-1);
}
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, struct acm_op *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;
}
/************************ get decision ******************************/
/* this example uses two domain ids and retrieves the decision if these domains
* can share information (useful, i.e., to enforce policy onto network traffic in dom0
*/
int acm_get_decision(int xc_handle, int argc, char *const argv[])
{
struct acm_op op;
int ret;
op.cmd = ACM_GETDECISION;
op.interface_version = ACM_INTERFACE_VERSION;
op.u.getdecision.get_decision_by1 = UNSET;
op.u.getdecision.get_decision_by2 = UNSET;
op.u.getdecision.hook = SHARING;
while (1) {
int c = getopt(argc, argv, "i:s:");
if (c == -1)
break;
if (c == 'i') {
if (op.u.getdecision.get_decision_by1 == UNSET) {
op.u.getdecision.get_decision_by1 = DOMAINID;
op.u.getdecision.id1.domainid = strtoul(optarg, NULL, 0);
} else if (op.u.getdecision.get_decision_by2 == UNSET) {
op.u.getdecision.get_decision_by2 = DOMAINID;
op.u.getdecision.id2.domainid = strtoul(optarg, NULL, 0);
} else
usage(argv[0]);
} else if (c == 's') {
if (op.u.getdecision.get_decision_by1 == UNSET) {
op.u.getdecision.get_decision_by1 = SSIDREF;
op.u.getdecision.id1.ssidref = strtoul(optarg, NULL, 0);
} else if (op.u.getdecision.get_decision_by2 == UNSET) {
op.u.getdecision.get_decision_by2 = SSIDREF;
op.u.getdecision.id2.ssidref = strtoul(optarg, NULL, 0);
} else
usage(argv[0]);
} else
usage(argv[0]);
}
if ((op.u.getdecision.get_decision_by1 == UNSET) ||
(op.u.getdecision.get_decision_by2 == UNSET))
usage(argv[0]);
if ((ret = do_acm_op(xc_handle, &op))) {
printf("%s: Error getting decision (%d).\n", __func__, ret);
printf("%s: decision = %s.\n", __func__,
(op.u.getdecision.acm_decision ==
ACM_ACCESS_PERMITTED) ? "PERMITTED" : ((op.u.getdecision.
acm_decision ==
ACM_ACCESS_DENIED)
? "DENIED" :
"ERROR"));
return ret;
}
return op.u.getdecision.acm_decision;
}
/***************************** main **************************************/
int main(int argc, char **argv)
{
int acm_cmd_fd, ret = 0;
if (argc < 5)
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);
}
ret = acm_get_decision(acm_cmd_fd, argc, argv);
printf("Decision: %s (%d)\n",
(ret == ACM_ACCESS_PERMITTED) ? "PERMITTED" :
((ret == ACM_ACCESS_DENIED) ? "DENIED" : "ERROR"), ret);
close(acm_cmd_fd);
return ret;
}