aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>2007-03-29 19:26:13 +0100
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>2007-03-29 19:26:13 +0100
commit7f6d8fe5c9edca501420059a857116e42cd409ee (patch)
tree675e369c9728c656bb291c3c7dbeed3504cd2e09
parent61e7893dafdfa84717d362986c8328effd1a2320 (diff)
downloadxen-7f6d8fe5c9edca501420059a857116e42cd409ee.tar.gz
xen-7f6d8fe5c9edca501420059a857116e42cd409ee.tar.bz2
xen-7f6d8fe5c9edca501420059a857116e42cd409ee.zip
acm: Provide the possibility to choose the VM label of domain-0 in the
kernel line in grub.conf. The format is ssidref=<ssidref>:sHype:<policy name>:<vm label>. The name of the policy specified here must be the same name as the in the policy provided as a module during boot, otherwise the policy will not be accepted and the system then starts without a policy. The user tool for 'xm dumppolicy' has been adapted to show which entry in the binary policy is used by domain-0. Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
-rw-r--r--tools/security/secpol_tool.c59
-rw-r--r--tools/security/secpol_xml2bin.c3
-rw-r--r--xen/acm/acm_chinesewall_hooks.c13
-rw-r--r--xen/acm/acm_core.c65
-rw-r--r--xen/acm/acm_null_hooks.c2
-rw-r--r--xen/acm/acm_policy.c10
-rw-r--r--xen/acm/acm_simple_type_enforcement_hooks.c26
-rw-r--r--xen/include/acm/acm_core.h9
-rw-r--r--xen/include/acm/acm_hooks.h12
9 files changed, 163 insertions, 36 deletions
diff --git a/tools/security/secpol_tool.c b/tools/security/secpol_tool.c
index 0b9c3e4acd..a4a782c754 100644
--- a/tools/security/secpol_tool.c
+++ b/tools/security/secpol_tool.c
@@ -57,7 +57,7 @@ void usage(char *progname)
/*************************** DUMPS *******************************/
-void acm_dump_chinesewall_buffer(void *buf, int buflen)
+void acm_dump_chinesewall_buffer(void *buf, int buflen, uint16_t chwall_ref)
{
struct acm_chwall_policy_buffer *cwbuf =
@@ -91,6 +91,8 @@ void acm_dump_chinesewall_buffer(void *buf, int buflen)
for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++)
printf("%02x ",
ntohs(ssids[i * ntohl(cwbuf->chwall_max_types) + j]));
+ if (i == chwall_ref)
+ printf(" <-- Domain-0");
}
printf("\n\nConfict Sets:\n");
conflicts =
@@ -131,7 +133,7 @@ void acm_dump_chinesewall_buffer(void *buf, int buflen)
}
}
-void acm_dump_ste_buffer(void *buf, int buflen)
+void acm_dump_ste_buffer(void *buf, int buflen, uint16_t ste_ref)
{
struct acm_ste_policy_buffer *stebuf =
@@ -158,11 +160,14 @@ void acm_dump_ste_buffer(void *buf, int buflen)
for (j = 0; j < ntohl(stebuf->ste_max_types); j++)
printf("%02x ",
ntohs(ssids[i * ntohl(stebuf->ste_max_types) + j]));
+ if (i == ste_ref)
+ printf(" <-- Domain-0");
}
printf("\n\n");
}
-void acm_dump_policy_buffer(void *buf, int buflen)
+void acm_dump_policy_buffer(void *buf, int buflen,
+ uint16_t chwall_ref, uint16_t ste_ref)
{
struct acm_policy_buffer *pol = (struct acm_policy_buffer *) buf;
char *policy_reference_name =
@@ -190,13 +195,15 @@ void acm_dump_policy_buffer(void *buf, int buflen)
acm_dump_chinesewall_buffer(ALIGN8(buf +
ntohl(pol->primary_buffer_offset)),
ntohl(pol->len) -
- ntohl(pol->primary_buffer_offset));
+ ntohl(pol->primary_buffer_offset),
+ chwall_ref);
break;
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
acm_dump_ste_buffer(ALIGN8(buf + ntohl(pol->primary_buffer_offset)),
ntohl(pol->len) -
- ntohl(pol->primary_buffer_offset));
+ ntohl(pol->primary_buffer_offset),
+ ste_ref);
break;
case ACM_NULL_POLICY:
@@ -212,13 +219,15 @@ void acm_dump_policy_buffer(void *buf, int buflen)
acm_dump_chinesewall_buffer(ALIGN8(buf +
ntohl(pol->secondary_buffer_offset)),
ntohl(pol->len) -
- ntohl(pol->secondary_buffer_offset));
+ ntohl(pol->secondary_buffer_offset),
+ chwall_ref);
break;
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
acm_dump_ste_buffer(ALIGN8(buf + ntohl(pol->secondary_buffer_offset)),
ntohl(pol->len) -
- ntohl(pol->secondary_buffer_offset));
+ ntohl(pol->secondary_buffer_offset),
+ ste_ref);
break;
case ACM_NULL_POLICY:
@@ -230,6 +239,27 @@ void acm_dump_policy_buffer(void *buf, int buflen)
}
}
+/************************** get dom0 ssidref *****************************/
+int acm_get_ssidref(int xc_handle, int domid, uint16_t *chwall_ref,
+ uint16_t *ste_ref)
+{
+ int ret;
+ struct acm_getssid getssid;
+ char buf[4096];
+ struct acm_ssid_buffer *ssid = (struct acm_ssid_buffer *)buf;
+ getssid.interface_version = ACM_INTERFACE_VERSION;
+ set_xen_guest_handle(getssid.ssidbuf, buf);
+ getssid.ssidbuf_size = sizeof(buf);
+ getssid.get_ssid_by = ACM_GETBY_domainid;
+ getssid.id.domainid = domid;
+ ret = xc_acm_op(xc_handle, ACMOP_getssid, &getssid, sizeof(getssid));
+ if (ret == 0) {
+ *chwall_ref = ssid->ssidref & 0xffff;
+ *ste_ref = ssid->ssidref >> 16;
+ }
+ return ret;
+}
+
/******************************* get policy ******************************/
#define PULL_CACHE_SIZE 8192
@@ -239,12 +269,16 @@ int acm_domain_getpolicy(int xc_handle)
{
struct acm_getpolicy getpolicy;
int ret;
+ uint16_t chwall_ref, ste_ref;
memset(pull_buffer, 0x00, sizeof(pull_buffer));
getpolicy.interface_version = ACM_INTERFACE_VERSION;
set_xen_guest_handle(getpolicy.pullcache, pull_buffer);
getpolicy.pullcache_size = sizeof(pull_buffer);
ret = xc_acm_op(xc_handle, ACMOP_getpolicy, &getpolicy, sizeof(getpolicy));
+ if (ret >= 0) {
+ ret = acm_get_ssidref(xc_handle, 0, &chwall_ref, &ste_ref);
+ }
if (ret < 0) {
printf("ACM operation failed: errno=%d\n", errno);
@@ -254,7 +288,9 @@ int acm_domain_getpolicy(int xc_handle)
}
/* dump policy */
- acm_dump_policy_buffer(pull_buffer, sizeof(pull_buffer));
+ acm_dump_policy_buffer(pull_buffer, sizeof(pull_buffer),
+ chwall_ref, ste_ref);
+
return ret;
}
@@ -266,6 +302,7 @@ int acm_domain_loadpolicy(int xc_handle, const char *filename)
int ret, fd;
off_t len;
uint8_t *buffer;
+ uint16_t chwall_ssidref, ste_ssidref;
if ((ret = stat(filename, &mystat))) {
printf("File %s not found.\n", filename);
@@ -282,10 +319,14 @@ int acm_domain_loadpolicy(int xc_handle, const char *filename)
printf("File %s not found.\n", filename);
goto free_out;
}
+ ret =acm_get_ssidref(xc_handle, 0, &chwall_ssidref, &ste_ssidref);
+ if (ret < 0) {
+ goto free_out;
+ }
if (len == read(fd, buffer, len)) {
struct acm_setpolicy setpolicy;
/* dump it and then push it down into xen/acm */
- acm_dump_policy_buffer(buffer, len);
+ acm_dump_policy_buffer(buffer, len, chwall_ssidref, ste_ssidref);
setpolicy.interface_version = ACM_INTERFACE_VERSION;
set_xen_guest_handle(setpolicy.pushcache, buffer);
setpolicy.pushcache_size = len;
diff --git a/tools/security/secpol_xml2bin.c b/tools/security/secpol_xml2bin.c
index 581ede1b64..4b8f1dc7cd 100644
--- a/tools/security/secpol_xml2bin.c
+++ b/tools/security/secpol_xml2bin.c
@@ -1163,7 +1163,8 @@ int write_binary(char *filename)
u_int32_t len_ste = 0, len_chwall = 0, len_pr = 0; /* length of policy components */
- sscanf(policy_version_string,"%d.%d", &major, &minor);
+ if (policy_version_string)
+ sscanf(policy_version_string,"%d.%d", &major, &minor);
/* open binary file */
if ((fd =
diff --git a/xen/acm/acm_chinesewall_hooks.c b/xen/acm/acm_chinesewall_hooks.c
index 05f95256d0..c3797e90fc 100644
--- a/xen/acm/acm_chinesewall_hooks.c
+++ b/xen/acm/acm_chinesewall_hooks.c
@@ -41,6 +41,9 @@
#include <acm/acm_core.h>
#include <acm/acm_hooks.h>
#include <acm/acm_endian.h>
+#include <acm/acm_core.h>
+
+ssidref_t dom0_chwall_ssidref = 0x0001;
/* local cache structures for chinese wall policy */
struct chwall_binary_policy chwall_bin_pol;
@@ -53,7 +56,7 @@ int acm_init_chwall_policy(void)
{
/* minimal startup policy; policy write-locked already */
chwall_bin_pol.max_types = 1;
- chwall_bin_pol.max_ssidrefs = 2;
+ chwall_bin_pol.max_ssidrefs = 1 + dom0_chwall_ssidref;
chwall_bin_pol.max_conflictsets = 1;
chwall_bin_pol.ssidrefs =
(domaintype_t *) xmalloc_array(domaintype_t,
@@ -254,7 +257,7 @@ chwall_init_state(struct acm_chwall_policy_buffer *chwall_buf,
* more than one type is currently running */
}
-static int chwall_set_policy(u8 * buf, u32 buf_size)
+static int chwall_set_policy(u8 * buf, u32 buf_size, int is_bootpolicy)
{
/* policy write-locked already */
struct acm_chwall_policy_buffer *chwall_buf =
@@ -286,6 +289,12 @@ static int chwall_set_policy(u8 * buf, u32 buf_size)
(chwall_buf->policy_version != ACM_CHWALL_VERSION))
return -EINVAL;
+ /* during boot dom0_chwall_ssidref is set */
+ if (is_bootpolicy &&
+ (dom0_chwall_ssidref >= chwall_buf->chwall_max_ssidrefs)) {
+ goto error_free;
+ }
+
/* 1. allocate new buffers */
ssids =
xmalloc_array(domaintype_t,
diff --git a/xen/acm/acm_core.c b/xen/acm/acm_core.c
index d7becf3510..57db1369f5 100644
--- a/xen/acm/acm_core.c
+++ b/xen/acm/acm_core.c
@@ -62,18 +62,63 @@ struct acm_binary_policy acm_bin_pol;
/* acm binary policy lock */
DEFINE_RWLOCK(acm_bin_pol_rwlock);
+/* ACM's only accepted policy name */
+char polname[80];
+char *acm_accepted_boot_policy_name = NULL;
+
+static void __init set_dom0_ssidref(const char *val)
+{
+ /* expected format:
+ ssidref=<hex number>:<policy name>
+ Policy name must not have a 'space'.
+ */
+ const char *c;
+ int lo, hi;
+ int i;
+ int dom0_ssidref = simple_strtoull(val, &c, 0);
+
+ if (!strncmp(&c[0],":sHype:", 7)) {
+ lo = dom0_ssidref & 0xffff;
+ if (lo < ACM_MAX_NUM_TYPES && lo >= 1)
+ dom0_chwall_ssidref = lo;
+ hi = dom0_ssidref >> 16;
+ if (hi < ACM_MAX_NUM_TYPES && hi >= 1)
+ dom0_ste_ssidref = hi;
+ for (i = 0; i < sizeof(polname); i++) {
+ polname[i] = c[7+i];
+ if (polname[i] == '\0' || polname[i] == '\t' ||
+ polname[i] == '\n' || polname[i] == ' ' ||
+ polname[i] == ':') {
+ break;
+ }
+ }
+ polname[i] = 0;
+ acm_accepted_boot_policy_name = polname;
+ }
+}
+
+custom_param("ssidref", set_dom0_ssidref);
+
int
acm_set_policy_reference(u8 *buf, u32 buf_size)
{
+ char *name = (char *)(buf + sizeof(struct acm_policy_reference_buffer));
struct acm_policy_reference_buffer *pr = (struct acm_policy_reference_buffer *)buf;
+
+ if (acm_accepted_boot_policy_name != NULL) {
+ if (strcmp(acm_accepted_boot_policy_name, name)) {
+ printk("Policy's name '%s' is not the expected one '%s'.\n",
+ name, acm_accepted_boot_policy_name);
+ return ACM_ERROR;
+ }
+ }
+
acm_bin_pol.policy_reference_name = (char *)xmalloc_array(u8, be32_to_cpu(pr->len));
if (!acm_bin_pol.policy_reference_name)
return -ENOMEM;
+ strlcpy(acm_bin_pol.policy_reference_name, name, be32_to_cpu(pr->len));
- strlcpy(acm_bin_pol.policy_reference_name,
- (char *)(buf + sizeof(struct acm_policy_reference_buffer)),
- be32_to_cpu(pr->len));
printk("%s: Activating policy %s\n", __func__,
acm_bin_pol.policy_reference_name);
return 0;
@@ -190,7 +235,8 @@ acm_is_policy(char *buf, unsigned long len)
static int
acm_setup(char *policy_start,
- unsigned long policy_len)
+ unsigned long policy_len,
+ int is_bootpolicy)
{
int rc = ACM_OK;
struct acm_policy_buffer *pol;
@@ -202,7 +248,8 @@ acm_setup(char *policy_start,
if (be32_to_cpu(pol->magic) != ACM_MAGIC)
return rc;
- rc = do_acm_set_policy((void *)policy_start, (u32)policy_len);
+ rc = do_acm_set_policy((void *)policy_start, (u32)policy_len,
+ is_bootpolicy);
if (rc == ACM_OK)
{
printkd("Policy len 0x%lx, start at %p.\n",policy_len,policy_start);
@@ -224,7 +271,10 @@ acm_init(char *policy_start,
int ret = ACM_OK;
/* first try to load the boot policy (uses its own locks) */
- acm_setup(policy_start, policy_len);
+ acm_setup(policy_start, policy_len, 1);
+
+ /* a user-provided policy may have any name; only matched during boot */
+ acm_accepted_boot_policy_name = NULL;
if (acm_active_security_policy != ACM_POLICY_UNDEFINED)
{
@@ -236,6 +286,9 @@ acm_init(char *policy_start,
printk("%s: Loading default policy (%s).\n",
__func__, ACM_POLICY_NAME(ACM_DEFAULT_SECURITY_POLICY));
+ /* (re-)set dom-0 ssidref to default */
+ dom0_ste_ssidref = dom0_chwall_ssidref = 0x0001;
+
if (acm_init_binary_policy(ACM_DEFAULT_SECURITY_POLICY)) {
ret = -EINVAL;
goto out;
diff --git a/xen/acm/acm_null_hooks.c b/xen/acm/acm_null_hooks.c
index 27d949378f..f481b71ed4 100644
--- a/xen/acm/acm_null_hooks.c
+++ b/xen/acm/acm_null_hooks.c
@@ -33,7 +33,7 @@ null_dump_binary_policy(u8 *buf, u32 buf_size)
}
static int
-null_set_binary_policy(u8 *buf, u32 buf_size)
+null_set_binary_policy(u8 *buf, u32 buf_size, int is_bootpolicy)
{
return ACM_OK;
}
diff --git a/xen/acm/acm_policy.c b/xen/acm/acm_policy.c
index 694bd9daa1..96186895c7 100644
--- a/xen/acm/acm_policy.c
+++ b/xen/acm/acm_policy.c
@@ -50,7 +50,7 @@ acm_set_policy(XEN_GUEST_HANDLE(void) buf, u32 buf_size)
printk("%s: Error copying!\n",__func__);
goto error_free;
}
- ret = do_acm_set_policy(policy_buffer, buf_size);
+ ret = do_acm_set_policy(policy_buffer, buf_size, 0);
error_free:
xfree(policy_buffer);
@@ -59,7 +59,7 @@ acm_set_policy(XEN_GUEST_HANDLE(void) buf, u32 buf_size)
int
-do_acm_set_policy(void *buf, u32 buf_size)
+do_acm_set_policy(void *buf, u32 buf_size, int is_bootpolicy)
{
struct acm_policy_buffer *pol = (struct acm_policy_buffer *)buf;
uint32_t offset, length;
@@ -106,14 +106,16 @@ do_acm_set_policy(void *buf, u32 buf_size)
length = be32_to_cpu(pol->secondary_buffer_offset) - offset;
if ( (offset + length) > buf_size ||
- acm_primary_ops->set_binary_policy(buf + offset, length))
+ acm_primary_ops->set_binary_policy(buf + offset, length,
+ is_bootpolicy))
goto error_lock_free;
/* set secondary policy data */
offset = be32_to_cpu(pol->secondary_buffer_offset);
length = be32_to_cpu(pol->len) - offset;
if ( (offset + length) > buf_size ||
- acm_secondary_ops->set_binary_policy(buf + offset, length))
+ acm_secondary_ops->set_binary_policy(buf + offset, length,
+ is_bootpolicy))
goto error_lock_free;
memcpy(&acm_bin_pol.xml_pol_version,
diff --git a/xen/acm/acm_simple_type_enforcement_hooks.c b/xen/acm/acm_simple_type_enforcement_hooks.c
index f5793a22d8..e87d0a25c1 100644
--- a/xen/acm/acm_simple_type_enforcement_hooks.c
+++ b/xen/acm/acm_simple_type_enforcement_hooks.c
@@ -31,6 +31,9 @@
#include <acm/acm_hooks.h>
#include <asm/atomic.h>
#include <acm/acm_endian.h>
+#include <acm/acm_core.h>
+
+ssidref_t dom0_ste_ssidref = 0x0001;
/* local cache structures for STE policy */
struct ste_binary_policy ste_bin_pol;
@@ -74,15 +77,21 @@ int acm_init_ste_policy(void)
{
/* minimal startup policy; policy write-locked already */
ste_bin_pol.max_types = 1;
- ste_bin_pol.max_ssidrefs = 2;
- ste_bin_pol.ssidrefs = (domaintype_t *)xmalloc_array(domaintype_t, 2);
- memset(ste_bin_pol.ssidrefs, 0, 2);
+ ste_bin_pol.max_ssidrefs = 1 + dom0_ste_ssidref;
+ ste_bin_pol.ssidrefs =
+ (domaintype_t *)xmalloc_array(domaintype_t,
+ ste_bin_pol.max_types *
+ ste_bin_pol.max_ssidrefs);
if (ste_bin_pol.ssidrefs == NULL)
return ACM_INIT_SSID_ERROR;
- /* initialize state so that dom0 can start up and communicate with itself */
- ste_bin_pol.ssidrefs[1] = 1;
+ memset(ste_bin_pol.ssidrefs, 0, sizeof(domaintype_t) *
+ ste_bin_pol.max_types *
+ ste_bin_pol.max_ssidrefs);
+
+ /* initialize state so that dom0 can start up and communicate with itself */
+ ste_bin_pol.ssidrefs[ste_bin_pol.max_types * dom0_ste_ssidref] = 1;
/* init stats */
atomic_set(&(ste_bin_pol.ec_eval_count), 0);
@@ -274,7 +283,7 @@ ste_init_state(struct acm_ste_policy_buffer *ste_buf, domaintype_t *ssidrefs)
/* set new policy; policy write-locked already */
static int
-ste_set_policy(u8 *buf, u32 buf_size)
+ste_set_policy(u8 *buf, u32 buf_size, int is_bootpolicy)
{
struct acm_ste_policy_buffer *ste_buf = (struct acm_ste_policy_buffer *)buf;
void *ssidrefsbuf;
@@ -305,6 +314,11 @@ ste_set_policy(u8 *buf, u32 buf_size)
if (ste_buf->ste_ssid_offset + sizeof(domaintype_t) * ste_buf->ste_max_ssidrefs*ste_buf->ste_max_types > buf_size)
goto error_free;
+ /* during boot dom0_chwall_ssidref is set */
+ if (is_bootpolicy && (dom0_ste_ssidref >= ste_buf->ste_max_ssidrefs)) {
+ goto error_free;
+ }
+
arrcpy(ssidrefsbuf,
buf + ste_buf->ste_ssid_offset,
sizeof(domaintype_t),
diff --git a/xen/include/acm/acm_core.h b/xen/include/acm/acm_core.h
index 033a1fd418..a09294cfc9 100644
--- a/xen/include/acm/acm_core.h
+++ b/xen/include/acm/acm_core.h
@@ -123,13 +123,20 @@ int acm_init_domain_ssid(domid_t id, ssidref_t ssidref);
void acm_free_domain_ssid(struct acm_ssid_domain *ssid);
int acm_init_binary_policy(u32 policy_code);
int acm_set_policy(XEN_GUEST_HANDLE(void) buf, u32 buf_size);
-int do_acm_set_policy(void *buf, u32 buf_size);
+int do_acm_set_policy(void *buf, u32 buf_size, int is_bootpolicy);
int acm_get_policy(XEN_GUEST_HANDLE(void) buf, u32 buf_size);
int acm_dump_statistics(XEN_GUEST_HANDLE(void) buf, u16 buf_size);
int acm_get_ssid(ssidref_t ssidref, XEN_GUEST_HANDLE(void) buf, u16 buf_size);
int acm_get_decision(ssidref_t ssidref1, ssidref_t ssidref2, u32 hook);
int acm_set_policy_reference(u8 * buf, u32 buf_size);
int acm_dump_policy_reference(u8 *buf, u32 buf_size);
+
+
+/* variables */
+extern ssidref_t dom0_chwall_ssidref;
+extern ssidref_t dom0_ste_ssidref;
+#define ACM_MAX_NUM_TYPES (256)
+
#endif
/*
diff --git a/xen/include/acm/acm_hooks.h b/xen/include/acm/acm_hooks.h
index 2ac8a4ab44..0a771dd794 100644
--- a/xen/include/acm/acm_hooks.h
+++ b/xen/include/acm/acm_hooks.h
@@ -91,7 +91,8 @@ struct acm_operations {
int (*init_domain_ssid) (void **ssid, ssidref_t ssidref);
void (*free_domain_ssid) (void *ssid);
int (*dump_binary_policy) (u8 *buffer, u32 buf_size);
- int (*set_binary_policy) (u8 *buffer, u32 buf_size);
+ int (*set_binary_policy) (u8 *buffer, u32 buf_size,
+ int is_bootpolicy);
int (*dump_statistics) (u8 *buffer, u16 buf_size);
int (*dump_ssid_types) (ssidref_t ssidref, u8 *buffer, u16 buf_size);
/* domain management control hooks (can be NULL) */
@@ -347,14 +348,13 @@ static inline int acm_pre_grant_setup(domid_t id)
}
}
-/* predefined ssidref for DOM0 used by xen when creating DOM0 */
-#define ACM_DOM0_SSIDREF 0x00010001
-
static inline void acm_post_domain0_create(domid_t domid)
{
/* initialialize shared sHype security labels for new domain */
- acm_init_domain_ssid(domid, ACM_DOM0_SSIDREF);
- acm_post_domain_create(domid, ACM_DOM0_SSIDREF);
+ int dom0_ssidref = dom0_ste_ssidref << 16 | dom0_chwall_ssidref;
+
+ acm_init_domain_ssid(domid, dom0_ssidref);
+ acm_post_domain_create(domid, dom0_ssidref);
}
static inline int acm_sharing(ssidref_t ssidref1, ssidref_t ssidref2)