mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
Xen Security Modules: XSM
Signed-off-by: George Coker <gscoker@alpha.ncsc.mil>
This commit is contained in:
1 parent
3d030c1164
commit
d046f361dc
31 files changed
+1665
-4
No files matched your search
@@ -78,10 +78,12 @@ CFLAGS += $(call cc-option,$(CC),-Wdeclaration-after-statement,)
|
||||
LDFLAGS += $(foreach i, $(EXTRA_LIB), -L$(i))
|
||||
CFLAGS += $(foreach i, $(EXTRA_INCLUDES), -I$(i))
|
||||
|
||||
# Enable XSM security module. Enabling XSM requires selection of an
|
||||
# XSM security module.
|
||||
XSM_ENABLE ?= n
|
||||
|
||||
# If ACM_SECURITY = y, then the access control module is compiled
|
||||
# into Xen and the policy type can be set by the boot policy file
|
||||
# y - Build the Xen ACM framework
|
||||
# n - Do not build the Xen ACM framework
|
||||
ACM_SECURITY ?= n
|
||||
|
||||
# Optional components
|
||||
|
||||
+2
-1
@@ -56,6 +56,7 @@ _clean: delete-unfresh-files
|
||||
$(MAKE) -f $(BASEDIR)/Rules.mk -C common clean
|
||||
$(MAKE) -f $(BASEDIR)/Rules.mk -C drivers clean
|
||||
$(MAKE) -f $(BASEDIR)/Rules.mk -C acm clean
|
||||
$(MAKE) -f $(BASEDIR)/Rules.mk -C xsm clean
|
||||
$(MAKE) -f $(BASEDIR)/Rules.mk -C arch/$(TARGET_ARCH) clean
|
||||
rm -f include/asm *.o $(TARGET)* *~ core
|
||||
rm -f include/asm-*/asm-offsets.h
|
||||
@@ -122,7 +123,7 @@ include/asm-$(TARGET_ARCH)/asm-offsets.h: arch/$(TARGET_ARCH)/asm-offsets.s
|
||||
build-headers:
|
||||
$(MAKE) -C include/public/foreign
|
||||
|
||||
SUBDIRS = acm arch/$(TARGET_ARCH) common drivers
|
||||
SUBDIRS = xsm acm arch/$(TARGET_ARCH) common drivers
|
||||
define all_sources
|
||||
( find include/asm-$(TARGET_ARCH) -name '*.h' -print; \
|
||||
find include -name 'asm-*' -prune -o -name '*.h' -print; \
|
||||
|
||||
@@ -52,10 +52,12 @@ HDRS := $(filter-out %/asm-offsets.h,$(AHDRS))
|
||||
# Note that link order matters!
|
||||
ALL_OBJS-y += $(BASEDIR)/common/built_in.o
|
||||
ALL_OBJS-y += $(BASEDIR)/drivers/built_in.o
|
||||
ALL_OBJS-y += $(BASEDIR)/xsm/built_in.o
|
||||
ALL_OBJS-$(ACM_SECURITY) += $(BASEDIR)/acm/built_in.o
|
||||
ALL_OBJS-y += $(BASEDIR)/arch/$(TARGET_ARCH)/built_in.o
|
||||
|
||||
CFLAGS-y += -g -D__XEN__
|
||||
CFLAGS-$(XSM_ENABLE) += -DXSM_ENABLE
|
||||
CFLAGS-$(ACM_SECURITY) += -DACM_SECURITY
|
||||
CFLAGS-$(verbose) += -DVERBOSE
|
||||
CFLAGS-$(crash_debug) += -DCRASH_DEBUG
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <asm/hvm/hvm.h>
|
||||
#include <asm/hvm/support.h>
|
||||
#include <asm/processor.h>
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
long arch_do_domctl(
|
||||
struct xen_domctl *domctl,
|
||||
@@ -64,6 +65,14 @@ long arch_do_domctl(
|
||||
if ( unlikely((d = rcu_lock_domain_by_id(domctl->domain)) == NULL) )
|
||||
break;
|
||||
|
||||
ret = xsm_ioport_permission(d, fp,
|
||||
domctl->u.ioport_permission.allow_access);
|
||||
if ( ret )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
break;
|
||||
}
|
||||
|
||||
if ( np == 0 )
|
||||
ret = 0;
|
||||
else if ( domctl->u.ioport_permission.allow_access )
|
||||
@@ -90,6 +99,13 @@ long arch_do_domctl(
|
||||
|
||||
page = mfn_to_page(mfn);
|
||||
|
||||
ret = xsm_getpageframeinfo(page);
|
||||
if ( ret )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
break;
|
||||
}
|
||||
|
||||
if ( likely(get_page(page, d)) )
|
||||
{
|
||||
ret = 0;
|
||||
@@ -173,6 +189,10 @@ long arch_do_domctl(
|
||||
|
||||
page = mfn_to_page(mfn);
|
||||
|
||||
ret = xsm_getpageframeinfo(page);
|
||||
if ( ret )
|
||||
continue;
|
||||
|
||||
if ( likely(mfn_valid(mfn) && get_page(page, d)) )
|
||||
{
|
||||
unsigned long type = 0;
|
||||
@@ -230,6 +250,13 @@ long arch_do_domctl(
|
||||
ret = -EINVAL;
|
||||
if ( d != NULL )
|
||||
{
|
||||
ret = xsm_getmemlist(d);
|
||||
if ( ret )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
spin_lock(&d->page_alloc_lock);
|
||||
@@ -269,6 +296,13 @@ long arch_do_domctl(
|
||||
if ( unlikely(d == NULL) )
|
||||
break;
|
||||
|
||||
ret = xsm_hypercall_init(d);
|
||||
if ( ret )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
break;
|
||||
}
|
||||
|
||||
mfn = gmfn_to_mfn(d, gmfn);
|
||||
|
||||
ret = -EACCES;
|
||||
@@ -304,6 +338,10 @@ long arch_do_domctl(
|
||||
if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_hvmcontext(d, domctl->cmd);
|
||||
if ( ret )
|
||||
goto sethvmcontext_out;
|
||||
|
||||
ret = -EINVAL;
|
||||
if ( !is_hvm_domain(d) )
|
||||
goto sethvmcontext_out;
|
||||
@@ -337,6 +375,10 @@ long arch_do_domctl(
|
||||
if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_hvmcontext(d, domctl->cmd);
|
||||
if ( ret )
|
||||
goto gethvmcontext_out;
|
||||
|
||||
ret = -EINVAL;
|
||||
if ( !is_hvm_domain(d) )
|
||||
goto gethvmcontext_out;
|
||||
@@ -390,6 +432,13 @@ long arch_do_domctl(
|
||||
if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_address_size(d, domctl->cmd);
|
||||
if ( ret )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
break;
|
||||
}
|
||||
|
||||
switch ( domctl->u.address_size.size )
|
||||
{
|
||||
#ifdef CONFIG_COMPAT
|
||||
@@ -417,6 +466,13 @@ long arch_do_domctl(
|
||||
if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_address_size(d, domctl->cmd);
|
||||
if ( ret )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
break;
|
||||
}
|
||||
|
||||
domctl->u.address_size.size = BITS_PER_GUEST_LONG(d);
|
||||
|
||||
ret = 0;
|
||||
|
||||
@@ -1069,6 +1069,10 @@ static int hvmop_set_pci_intx_level(
|
||||
if ( !is_hvm_domain(d) )
|
||||
goto out;
|
||||
|
||||
rc = xsm_hvm_set_pci_intx_level(d);
|
||||
if ( rc )
|
||||
goto out;
|
||||
|
||||
rc = 0;
|
||||
switch ( op.level )
|
||||
{
|
||||
@@ -1112,6 +1116,10 @@ static int hvmop_set_isa_irq_level(
|
||||
if ( !is_hvm_domain(d) )
|
||||
goto out;
|
||||
|
||||
rc = xsm_hvm_set_isa_irq_level(d);
|
||||
if ( rc )
|
||||
goto out;
|
||||
|
||||
rc = 0;
|
||||
switch ( op.level )
|
||||
{
|
||||
@@ -1155,6 +1163,10 @@ static int hvmop_set_pci_link_route(
|
||||
if ( !is_hvm_domain(d) )
|
||||
goto out;
|
||||
|
||||
rc = xsm_hvm_set_pci_link_route(d);
|
||||
if ( rc )
|
||||
goto out;
|
||||
|
||||
rc = 0;
|
||||
hvm_set_pci_link_route(d, op.link, op.isa_irq);
|
||||
|
||||
@@ -1204,6 +1216,10 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
|
||||
if ( !is_hvm_domain(d) )
|
||||
goto param_fail;
|
||||
|
||||
rc = xsm_hvm_param(d, op);
|
||||
if ( rc )
|
||||
goto param_fail;
|
||||
|
||||
if ( op == HVMOP_set_param )
|
||||
{
|
||||
switch ( a.index )
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
#include <asm/hypercall.h>
|
||||
#include <asm/shared.h>
|
||||
#include <public/memory.h>
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
#define MEM_LOG(_f, _a...) gdprintk(XENLOG_WARNING , _f "\n" , ## _a)
|
||||
|
||||
@@ -2048,6 +2049,10 @@ int do_mmuext_op(
|
||||
type = PGT_l4_page_table;
|
||||
|
||||
pin_page:
|
||||
rc = xsm_memory_pin_page(current->domain, page);
|
||||
if ( rc )
|
||||
break;
|
||||
|
||||
/* Ignore pinning of invalid paging levels. */
|
||||
if ( (op.cmd - MMUEXT_PIN_L1_TABLE) > (CONFIG_PAGING_LEVELS - 1) )
|
||||
break;
|
||||
@@ -2334,6 +2339,10 @@ int do_mmu_update(
|
||||
*/
|
||||
case MMU_NORMAL_PT_UPDATE:
|
||||
|
||||
rc = xsm_mmu_normal_update(current->domain, req.val);
|
||||
if ( rc )
|
||||
break;
|
||||
|
||||
gmfn = req.ptr >> PAGE_SHIFT;
|
||||
mfn = gmfn_to_mfn(d, gmfn);
|
||||
|
||||
@@ -2424,6 +2433,10 @@ int do_mmu_update(
|
||||
mfn = req.ptr >> PAGE_SHIFT;
|
||||
gpfn = req.val;
|
||||
|
||||
rc = xsm_mmu_machphys_update(current->domain, mfn);
|
||||
if ( rc )
|
||||
break;
|
||||
|
||||
if ( unlikely(!get_page_from_pagenr(mfn, FOREIGNDOM)) )
|
||||
{
|
||||
MEM_LOG("Could not get page for mach->phys update");
|
||||
@@ -2802,6 +2815,10 @@ int do_update_va_mapping(unsigned long va, u64 val64,
|
||||
if ( unlikely(!__addr_ok(va) && !paging_mode_external(d)) )
|
||||
return -EINVAL;
|
||||
|
||||
rc = xsm_update_va_mapping(current->domain, val);
|
||||
if ( rc )
|
||||
return rc;
|
||||
|
||||
LOCK_BIGLOCK(d);
|
||||
|
||||
pl1e = guest_map_l1e(v, va, &gl1mfn);
|
||||
@@ -3063,6 +3080,12 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
|
||||
else if ( (d = rcu_lock_domain_by_id(xatp.domid)) == NULL )
|
||||
return -ESRCH;
|
||||
|
||||
if ( xsm_add_to_physmap(current->domain, d) )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
switch ( xatp.space )
|
||||
{
|
||||
case XENMAPSPACE_shared_info:
|
||||
@@ -3139,6 +3162,13 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
|
||||
else if ( (d = rcu_lock_domain_by_id(fmap.domid)) == NULL )
|
||||
return -ESRCH;
|
||||
|
||||
rc = xsm_domain_memory_map(d);
|
||||
if ( rc )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = copy_from_guest(d->arch.e820, fmap.map.buffer,
|
||||
fmap.map.nr_entries) ? -EFAULT : 0;
|
||||
d->arch.nr_e820 = fmap.map.nr_entries;
|
||||
@@ -3172,10 +3202,15 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
|
||||
struct xen_memory_map memmap;
|
||||
XEN_GUEST_HANDLE(e820entry_t) buffer;
|
||||
int count;
|
||||
int rc;
|
||||
|
||||
if ( !IS_PRIV(current->domain) )
|
||||
return -EINVAL;
|
||||
|
||||
rc = xsm_machine_memory_map();
|
||||
if ( rc )
|
||||
return rc;
|
||||
|
||||
if ( copy_from_guest(&memmap, arg, 1) )
|
||||
return -EFAULT;
|
||||
if ( memmap.nr_entries < e820.nr_map + 1 )
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <asm/p2m.h>
|
||||
#include <asm/hap.h>
|
||||
#include <asm/guest_access.h>
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
/* Xen command-line option to enable hardware-assisted paging */
|
||||
int opt_hap_enabled;
|
||||
@@ -402,6 +403,10 @@ int paging_domctl(struct domain *d, xen_domctl_shadow_op_t *sc,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = xsm_shadow_control(d, sc->op);
|
||||
if ( rc )
|
||||
return rc;
|
||||
|
||||
/* Code to handle log-dirty. Note that some log dirty operations
|
||||
* piggy-back on shadow operations. For example, when
|
||||
* XEN_DOMCTL_SHADOW_OP_OFF is called, it first checks whether log dirty
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <asm/hypercall.h>
|
||||
#include <public/xen.h>
|
||||
#include <public/physdev.h>
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
#ifndef COMPAT
|
||||
typedef long ret_t;
|
||||
@@ -73,6 +74,9 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
|
||||
ret = -EPERM;
|
||||
if ( !IS_PRIV(v->domain) )
|
||||
break;
|
||||
ret = xsm_apic(v->domain, cmd);
|
||||
if ( ret )
|
||||
break;
|
||||
ret = ioapic_guest_read(apic.apic_physbase, apic.reg, &apic.value);
|
||||
if ( copy_to_guest(arg, &apic, 1) != 0 )
|
||||
ret = -EFAULT;
|
||||
@@ -87,6 +91,9 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
|
||||
ret = -EPERM;
|
||||
if ( !IS_PRIV(v->domain) )
|
||||
break;
|
||||
ret = xsm_apic(v->domain, cmd);
|
||||
if ( ret )
|
||||
break;
|
||||
ret = ioapic_guest_write(apic.apic_physbase, apic.reg, apic.value);
|
||||
break;
|
||||
}
|
||||
@@ -102,6 +109,10 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
|
||||
if ( !IS_PRIV(v->domain) )
|
||||
break;
|
||||
|
||||
ret = xsm_assign_vector(v->domain, irq_op.irq);
|
||||
if ( ret )
|
||||
break;
|
||||
|
||||
irq = irq_op.irq;
|
||||
ret = -EINVAL;
|
||||
if ( (irq < 0) || (irq >= NR_IRQS) )
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <asm/edd.h>
|
||||
#include <asm/mtrr.h>
|
||||
#include "cpu/mtrr/mtrr.h"
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
extern uint16_t boot_edid_caps;
|
||||
extern uint8_t boot_edid_info[];
|
||||
@@ -59,6 +60,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
|
||||
{
|
||||
case XENPF_settime:
|
||||
{
|
||||
ret = xsm_xen_settime();
|
||||
if ( ret )
|
||||
break;
|
||||
|
||||
do_settime(op->u.settime.secs,
|
||||
op->u.settime.nsecs,
|
||||
op->u.settime.system_time);
|
||||
@@ -68,6 +73,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
|
||||
|
||||
case XENPF_add_memtype:
|
||||
{
|
||||
ret = xsm_memtype(op->cmd);
|
||||
if ( ret )
|
||||
break;
|
||||
|
||||
ret = mtrr_add_page(
|
||||
op->u.add_memtype.mfn,
|
||||
op->u.add_memtype.nr_mfns,
|
||||
@@ -86,6 +95,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
|
||||
|
||||
case XENPF_del_memtype:
|
||||
{
|
||||
ret = xsm_memtype(op->cmd);
|
||||
if ( ret )
|
||||
break;
|
||||
|
||||
if (op->u.del_memtype.handle == 0
|
||||
/* mtrr/main.c otherwise does a lookup */
|
||||
&& (int)op->u.del_memtype.reg >= 0)
|
||||
@@ -105,6 +118,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
|
||||
unsigned int nr_mfns;
|
||||
mtrr_type type;
|
||||
|
||||
ret = xsm_memtype(op->cmd);
|
||||
if ( ret )
|
||||
break;
|
||||
|
||||
ret = -EINVAL;
|
||||
if ( op->u.read_memtype.reg < num_var_ranges )
|
||||
{
|
||||
@@ -120,6 +137,11 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
|
||||
case XENPF_microcode_update:
|
||||
{
|
||||
extern int microcode_update(XEN_GUEST_HANDLE(void), unsigned long len);
|
||||
|
||||
ret = xsm_microcode();
|
||||
if ( ret )
|
||||
break;
|
||||
|
||||
#ifndef COMPAT
|
||||
ret = microcode_update(op->u.microcode.data,
|
||||
op->u.microcode.length);
|
||||
@@ -136,6 +158,11 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
|
||||
{
|
||||
extern int opt_noirqbalance;
|
||||
int quirk_id = op->u.platform_quirk.quirk_id;
|
||||
|
||||
ret = xsm_platform_quirk(quirk_id);
|
||||
if ( ret )
|
||||
break;
|
||||
|
||||
switch ( quirk_id )
|
||||
{
|
||||
case QUIRK_NOIRQBALANCING:
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <acm/acm_hooks.h>
|
||||
#include <xen/kexec.h>
|
||||
#include <asm/edd.h>
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
#if defined(CONFIG_X86_64)
|
||||
#define BOOTSTRAP_DIRECTMAP_END (1UL << 32) /* 4GB */
|
||||
@@ -963,6 +964,8 @@ void __init __start_xen(unsigned long mbi_p)
|
||||
|
||||
percpu_init_areas();
|
||||
|
||||
xsm_init(&initrdidx, mbi, initial_images_start);
|
||||
|
||||
init_idle_domain();
|
||||
|
||||
trap_init();
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <asm/processor.h>
|
||||
#include <asm/numa.h>
|
||||
#include <xen/nodemask.h>
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
#define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0)
|
||||
|
||||
@@ -42,6 +43,10 @@ long arch_do_sysctl(
|
||||
|
||||
xen_sysctl_physinfo_t *pi = &sysctl->u.physinfo;
|
||||
|
||||
ret = xsm_physinfo();
|
||||
if ( ret )
|
||||
break;
|
||||
|
||||
pi->threads_per_core =
|
||||
cpus_weight(cpu_sibling_map[0]);
|
||||
pi->cores_per_socket =
|
||||
|
||||
@@ -676,6 +676,7 @@ ENTRY(hypercall_table)
|
||||
.long do_sysctl /* 35 */
|
||||
.long do_domctl
|
||||
.long do_kexec_op
|
||||
.long do_xsm_op
|
||||
.rept NR_hypercalls-((.-hypercall_table)/4)
|
||||
.long do_ni_hypercall
|
||||
.endr
|
||||
@@ -719,6 +720,7 @@ ENTRY(hypercall_args_table)
|
||||
.byte 1 /* do_sysctl */ /* 35 */
|
||||
.byte 1 /* do_domctl */
|
||||
.byte 2 /* do_kexec_op */
|
||||
.byte 1 /* do_xsm_op */
|
||||
.rept NR_hypercalls-(.-hypercall_args_table)
|
||||
.byte 0 /* do_ni_hypercall */
|
||||
.endr
|
||||
@@ -63,6 +63,8 @@ SECTIONS
|
||||
__initcall_start = .;
|
||||
.initcall.init : { *(.initcall1.init) } :text
|
||||
__initcall_end = .;
|
||||
.xsm_initcall.init : { __xsm_initcall_start = .;
|
||||
*(.xsm_initcall.init) __xsm_initcall_end = .; }
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
__init_end = .;
|
||||
|
||||
|
||||
@@ -612,6 +612,7 @@ ENTRY(hypercall_table)
|
||||
.quad do_sysctl /* 35 */
|
||||
.quad do_domctl
|
||||
.quad do_kexec_op
|
||||
.quad do_xsm_op
|
||||
.rept NR_hypercalls-((.-hypercall_table)/8)
|
||||
.quad do_ni_hypercall
|
||||
.endr
|
||||
@@ -655,6 +656,7 @@ ENTRY(hypercall_args_table)
|
||||
.byte 1 /* do_sysctl */ /* 35 */
|
||||
.byte 1 /* do_domctl */
|
||||
.byte 2 /* do_kexec */
|
||||
.byte 1 /* do_xsm_op */
|
||||
.rept NR_hypercalls-(.-hypercall_args_table)
|
||||
.byte 0 /* do_ni_hypercall */
|
||||
.endr
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <public/sched.h>
|
||||
#include <public/vcpu.h>
|
||||
#include <acm/acm_hooks.h>
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
/* Protect updates/reads (resp.) of domain_list and domain_hash. */
|
||||
DEFINE_SPINLOCK(domlist_update_lock);
|
||||
@@ -57,6 +58,13 @@ struct domain *alloc_domain(domid_t domid)
|
||||
|
||||
memset(d, 0, sizeof(*d));
|
||||
d->domain_id = domid;
|
||||
|
||||
if ( xsm_alloc_security_domain(d) != 0 )
|
||||
{
|
||||
free_domain(d);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
atomic_set(&d->refcnt, 1);
|
||||
spin_lock_init(&d->big_lock);
|
||||
spin_lock_init(&d->page_alloc_lock);
|
||||
@@ -69,6 +77,7 @@ struct domain *alloc_domain(domid_t domid)
|
||||
|
||||
void free_domain(struct domain *d)
|
||||
{
|
||||
xsm_free_security_domain(d);
|
||||
xfree(d);
|
||||
}
|
||||
|
||||
@@ -193,6 +202,9 @@ struct domain *domain_create(
|
||||
|
||||
if ( !is_idle_domain(d) )
|
||||
{
|
||||
if ( xsm_domain_create(d, ssidref) != 0 )
|
||||
goto fail;
|
||||
|
||||
d->is_paused_by_controller = 1;
|
||||
atomic_inc(&d->pause_count);
|
||||
|
||||
|
||||
+98
-1
@@ -24,6 +24,7 @@
|
||||
#include <asm/current.h>
|
||||
#include <public/domctl.h>
|
||||
#include <acm/acm_hooks.h>
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
extern long arch_do_domctl(
|
||||
struct xen_domctl *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl);
|
||||
@@ -127,7 +128,9 @@ void getdomaininfo(struct domain *d, struct xen_domctl_getdomaininfo *info)
|
||||
info->ssidref = ((struct acm_ssid_domain *)d->ssid)->ssidref;
|
||||
else
|
||||
info->ssidref = ACM_DEFAULT_SSID;
|
||||
|
||||
|
||||
xsm_security_domaininfo(d, info);
|
||||
|
||||
info->tot_pages = d->tot_pages;
|
||||
info->max_pages = d->max_pages;
|
||||
info->shared_info_frame = mfn_to_gmfn(d, __pa(d->shared_info)>>PAGE_SHIFT);
|
||||
@@ -204,6 +207,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
if ( d == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_setvcpucontext(d);
|
||||
if ( ret )
|
||||
goto svc_out;
|
||||
|
||||
ret = -EINVAL;
|
||||
if ( (vcpu >= MAX_VIRT_CPUS) || ((v = d->vcpu[vcpu]) == NULL) )
|
||||
goto svc_out;
|
||||
@@ -251,12 +258,17 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
ret = -ESRCH;
|
||||
if ( d != NULL )
|
||||
{
|
||||
ret = xsm_pausedomain(d);
|
||||
if ( ret )
|
||||
goto pausedomain_out;
|
||||
|
||||
ret = -EINVAL;
|
||||
if ( d != current->domain )
|
||||
{
|
||||
domain_pause_by_systemcontroller(d);
|
||||
ret = 0;
|
||||
}
|
||||
pausedomain_out:
|
||||
rcu_unlock_domain(d);
|
||||
}
|
||||
}
|
||||
@@ -270,6 +282,13 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
if ( d == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_unpausedomain(d);
|
||||
if ( ret )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
break;
|
||||
}
|
||||
|
||||
domain_unpause_by_systemcontroller(d);
|
||||
rcu_unlock_domain(d);
|
||||
ret = 0;
|
||||
@@ -284,6 +303,13 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
if ( d == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_resumedomain(d);
|
||||
if ( ret )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
break;
|
||||
}
|
||||
|
||||
domain_resume(d);
|
||||
rcu_unlock_domain(d);
|
||||
ret = 0;
|
||||
@@ -359,6 +385,13 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_max_vcpus(d);
|
||||
if ( ret )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Needed, for example, to ensure writable p.t. state is synced. */
|
||||
domain_pause(d);
|
||||
|
||||
@@ -395,12 +428,18 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
ret = -ESRCH;
|
||||
if ( d != NULL )
|
||||
{
|
||||
ret = xsm_destroydomain(d);
|
||||
if ( ret )
|
||||
goto destroydomain_out;
|
||||
|
||||
ret = -EINVAL;
|
||||
if ( d != current->domain )
|
||||
{
|
||||
domain_kill(d);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
destroydomain_out:
|
||||
rcu_unlock_domain(d);
|
||||
}
|
||||
}
|
||||
@@ -418,6 +457,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
if ( d == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_vcpuaffinity(op->cmd, d);
|
||||
if ( ret )
|
||||
goto vcpuaffinity_out;
|
||||
|
||||
ret = -EINVAL;
|
||||
if ( op->u.vcpuaffinity.vcpu >= MAX_VIRT_CPUS )
|
||||
goto vcpuaffinity_out;
|
||||
@@ -452,10 +495,15 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_scheduler(d);
|
||||
if ( ret )
|
||||
goto scheduler_op_out;
|
||||
|
||||
ret = sched_adjust(d, &op->u.scheduler_op);
|
||||
if ( copy_to_guest(u_domctl, op, 1) )
|
||||
ret = -EFAULT;
|
||||
|
||||
scheduler_op_out:
|
||||
rcu_unlock_domain(d);
|
||||
}
|
||||
break;
|
||||
@@ -478,12 +526,17 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
break;
|
||||
}
|
||||
|
||||
ret = xsm_getdomaininfo(d);
|
||||
if ( ret )
|
||||
goto getdomaininfo_out;
|
||||
|
||||
getdomaininfo(d, &op->u.getdomaininfo);
|
||||
|
||||
op->domain = op->u.getdomaininfo.domain;
|
||||
if ( copy_to_guest(u_domctl, op, 1) )
|
||||
ret = -EFAULT;
|
||||
|
||||
getdomaininfo_out:
|
||||
rcu_read_unlock(&domlist_read_lock);
|
||||
}
|
||||
break;
|
||||
@@ -498,6 +551,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_getvcpucontext(d);
|
||||
if ( ret )
|
||||
goto getvcpucontext_out;
|
||||
|
||||
ret = -EINVAL;
|
||||
if ( op->u.vcpucontext.vcpu >= MAX_VIRT_CPUS )
|
||||
goto getvcpucontext_out;
|
||||
@@ -554,6 +611,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_getvcpuinfo(d);
|
||||
if ( ret )
|
||||
goto getvcpuinfo_out;
|
||||
|
||||
ret = -EINVAL;
|
||||
if ( op->u.getvcpuinfo.vcpu >= MAX_VIRT_CPUS )
|
||||
goto getvcpuinfo_out;
|
||||
@@ -589,6 +650,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
if ( d == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_setdomainmaxmem(d);
|
||||
if ( ret )
|
||||
goto max_mem_out;
|
||||
|
||||
ret = -EINVAL;
|
||||
new_max = op->u.max_mem.max_memkb >> (PAGE_SHIFT-10);
|
||||
|
||||
@@ -603,6 +668,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
}
|
||||
spin_unlock(&d->page_alloc_lock);
|
||||
|
||||
max_mem_out:
|
||||
rcu_unlock_domain(d);
|
||||
}
|
||||
break;
|
||||
@@ -616,6 +682,13 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
if ( d == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_setdomainhandle(d);
|
||||
if ( ret )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(d->handle, op->u.setdomainhandle.handle,
|
||||
sizeof(xen_domain_handle_t));
|
||||
rcu_unlock_domain(d);
|
||||
@@ -632,6 +705,13 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
if ( d == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_setdebugging(d);
|
||||
if ( ret )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
break;
|
||||
}
|
||||
|
||||
domain_pause(d);
|
||||
d->debugger_attached = !!op->u.setdebugging.enable;
|
||||
domain_unpause(d); /* causes guest to latch new status */
|
||||
@@ -654,11 +734,16 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
if ( d == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_irq_permission(d, pirq, op->u.irq_permission.allow_access);
|
||||
if ( ret )
|
||||
goto irq_permission_out;
|
||||
|
||||
if ( op->u.irq_permission.allow_access )
|
||||
ret = irq_permit_access(d, pirq);
|
||||
else
|
||||
ret = irq_deny_access(d, pirq);
|
||||
|
||||
irq_permission_out:
|
||||
rcu_unlock_domain(d);
|
||||
}
|
||||
break;
|
||||
@@ -678,11 +763,16 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
if ( d == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_iomem_permission(d, mfn, op->u.iomem_permission.allow_access);
|
||||
if ( ret )
|
||||
goto iomem_permission_out;
|
||||
|
||||
if ( op->u.iomem_permission.allow_access )
|
||||
ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1);
|
||||
else
|
||||
ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1);
|
||||
|
||||
iomem_permission_out:
|
||||
rcu_unlock_domain(d);
|
||||
}
|
||||
break;
|
||||
@@ -695,6 +785,13 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
d = rcu_lock_domain_by_id(op->domain);
|
||||
if ( d != NULL )
|
||||
{
|
||||
ret = xsm_domain_settime(d);
|
||||
if ( ret )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
break;
|
||||
}
|
||||
|
||||
d->time_offset_seconds = op->u.settimeoffset.time_offset_seconds;
|
||||
rcu_unlock_domain(d);
|
||||
ret = 0;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <public/xen.h>
|
||||
#include <public/event_channel.h>
|
||||
#include <acm/acm_hooks.h>
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
#define bucket_from_port(d,p) \
|
||||
((d)->evtchn[(p)/EVTCHNS_PER_BUCKET])
|
||||
@@ -78,6 +79,7 @@ static int get_free_port(struct domain *d)
|
||||
{
|
||||
struct evtchn *chn;
|
||||
int port;
|
||||
int i, j;
|
||||
|
||||
if ( d->is_dying )
|
||||
return -EINVAL;
|
||||
@@ -95,6 +97,19 @@ static int get_free_port(struct domain *d)
|
||||
memset(chn, 0, EVTCHNS_PER_BUCKET * sizeof(*chn));
|
||||
bucket_from_port(d, port) = chn;
|
||||
|
||||
for ( i = 0; i < EVTCHNS_PER_BUCKET; i++ )
|
||||
{
|
||||
if ( xsm_alloc_security_evtchn(&chn[i]) )
|
||||
{
|
||||
for ( j = 0; j < i; j++ )
|
||||
{
|
||||
xsm_free_security_evtchn(&chn[j]);
|
||||
}
|
||||
xfree(chn);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
@@ -124,6 +139,10 @@ static long evtchn_alloc_unbound(evtchn_alloc_unbound_t *alloc)
|
||||
ERROR_EXIT(port);
|
||||
chn = evtchn_from_port(d, port);
|
||||
|
||||
rc = xsm_evtchn_unbound(d, chn, alloc->remote_dom);
|
||||
if ( rc )
|
||||
goto out;
|
||||
|
||||
chn->state = ECS_UNBOUND;
|
||||
if ( (chn->u.unbound.remote_domid = alloc->remote_dom) == DOMID_SELF )
|
||||
chn->u.unbound.remote_domid = current->domain->domain_id;
|
||||
@@ -180,6 +199,10 @@ static long evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind)
|
||||
(rchn->u.unbound.remote_domid != ld->domain_id) )
|
||||
ERROR_EXIT(-EINVAL);
|
||||
|
||||
rc = xsm_evtchn_interdomain(ld, lchn, rd, rchn);
|
||||
if ( rc )
|
||||
goto out;
|
||||
|
||||
lchn->u.interdomain.remote_dom = rd;
|
||||
lchn->u.interdomain.remote_port = (u16)rport;
|
||||
lchn->state = ECS_INTERDOMAIN;
|
||||
@@ -422,6 +445,8 @@ static long __evtchn_close(struct domain *d1, int port1)
|
||||
chn1->state = ECS_FREE;
|
||||
chn1->notify_vcpu_id = 0;
|
||||
|
||||
xsm_evtchn_close_post(chn1);
|
||||
|
||||
out:
|
||||
if ( d2 != NULL )
|
||||
{
|
||||
@@ -466,6 +491,10 @@ long evtchn_send(unsigned int lport)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = xsm_evtchn_send(ld, lchn);
|
||||
if ( ret )
|
||||
goto out;
|
||||
|
||||
switch ( lchn->state )
|
||||
{
|
||||
case ECS_INTERDOMAIN:
|
||||
@@ -495,6 +524,7 @@ long evtchn_send(unsigned int lport)
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock(&ld->evtchn_lock);
|
||||
|
||||
return ret;
|
||||
@@ -613,6 +643,11 @@ static long evtchn_status(evtchn_status_t *status)
|
||||
}
|
||||
|
||||
chn = evtchn_from_port(d, port);
|
||||
|
||||
rc = xsm_evtchn_status(d, chn);
|
||||
if ( rc )
|
||||
goto out;
|
||||
|
||||
switch ( chn->state )
|
||||
{
|
||||
case ECS_FREE:
|
||||
@@ -743,6 +778,7 @@ static long evtchn_reset(evtchn_reset_t *r)
|
||||
domid_t dom = r->dom;
|
||||
struct domain *d;
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
if ( dom == DOMID_SELF )
|
||||
dom = current->domain->domain_id;
|
||||
@@ -752,6 +788,13 @@ static long evtchn_reset(evtchn_reset_t *r)
|
||||
if ( (d = rcu_lock_domain_by_id(dom)) == NULL )
|
||||
return -ESRCH;
|
||||
|
||||
rc = xsm_evtchn_reset(current->domain, d);
|
||||
if ( rc )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
return rc;
|
||||
}
|
||||
|
||||
for ( i = 0; port_is_valid(d, i); i++ )
|
||||
(void)__evtchn_close(d, i);
|
||||
|
||||
@@ -969,7 +1012,10 @@ void evtchn_destroy(struct domain *d)
|
||||
/* Free all event-channel buckets. */
|
||||
spin_lock(&d->evtchn_lock);
|
||||
for ( i = 0; i < NR_EVTCHN_BUCKETS; i++ )
|
||||
{
|
||||
xsm_free_security_evtchn(d->evtchn[i]);
|
||||
xfree(d->evtchn[i]);
|
||||
}
|
||||
spin_unlock(&d->evtchn_lock);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <xen/guest_access.h>
|
||||
#include <xen/domain_page.h>
|
||||
#include <acm/acm_hooks.h>
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
#ifndef max_nr_grant_frames
|
||||
unsigned int max_nr_grant_frames = DEFAULT_MAX_NR_GRANT_FRAMES;
|
||||
@@ -224,6 +225,14 @@ __gnttab_map_grant_ref(
|
||||
return;
|
||||
}
|
||||
|
||||
rc = xsm_grant_mapref(ld, rd, op->flags);
|
||||
if ( rc )
|
||||
{
|
||||
rcu_unlock_domain(rd);
|
||||
op->status = GNTST_permission_denied;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( unlikely((handle = get_maptrack_handle(ld->grant_table)) == -1) )
|
||||
{
|
||||
rcu_unlock_domain(rd);
|
||||
@@ -451,6 +460,14 @@ __gnttab_unmap_common(
|
||||
return;
|
||||
}
|
||||
|
||||
rc = xsm_grant_unmapref(ld, rd);
|
||||
if ( rc )
|
||||
{
|
||||
rcu_unlock_domain(rd);
|
||||
op->status = GNTST_permission_denied;
|
||||
return;
|
||||
}
|
||||
|
||||
TRACE_1D(TRC_MEM_PAGE_GRANT_UNMAP, dom);
|
||||
|
||||
spin_lock(&rd->grant_table->lock);
|
||||
@@ -705,6 +722,13 @@ gnttab_setup_table(
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( xsm_grant_setup(current->domain, d) )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
op.status = GNTST_permission_denied;
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock(&d->grant_table->lock);
|
||||
|
||||
if ( (op.nr_frames > nr_grant_frames(d->grant_table)) &&
|
||||
@@ -745,6 +769,7 @@ gnttab_query_size(
|
||||
struct gnttab_query_size op;
|
||||
struct domain *d;
|
||||
domid_t dom;
|
||||
int rc;
|
||||
|
||||
if ( count != 1 )
|
||||
return -EINVAL;
|
||||
@@ -773,6 +798,14 @@ gnttab_query_size(
|
||||
goto query_out;
|
||||
}
|
||||
|
||||
rc = xsm_grant_query_size(current->domain, d);
|
||||
if ( rc )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
op.status = GNTST_permission_denied;
|
||||
goto query_out;
|
||||
}
|
||||
|
||||
spin_lock(&d->grant_table->lock);
|
||||
|
||||
op.nr_frames = nr_grant_frames(d->grant_table);
|
||||
@@ -919,6 +952,13 @@ gnttab_transfer(
|
||||
goto copyback;
|
||||
}
|
||||
|
||||
if ( xsm_grant_transfer(d, e) )
|
||||
{
|
||||
rcu_unlock_domain(e);
|
||||
gop.status = GNTST_permission_denied;
|
||||
goto copyback;
|
||||
}
|
||||
|
||||
spin_lock(&e->page_alloc_lock);
|
||||
|
||||
/*
|
||||
@@ -1139,6 +1179,13 @@ __gnttab_copy(
|
||||
PIN_FAIL(error_out, GNTST_bad_domain,
|
||||
"couldn't find %d\n", op->dest.domid);
|
||||
|
||||
rc = xsm_grant_copy(sd, dd);
|
||||
if ( rc )
|
||||
{
|
||||
rc = GNTST_permission_denied;
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if ( src_is_gref )
|
||||
{
|
||||
rc = __acquire_grant_for_copy(sd, op->source.u.ref, 1, &s_frame);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <xen/version.h>
|
||||
#include <xen/console.h>
|
||||
#include <public/elfnote.h>
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
#ifndef COMPAT
|
||||
|
||||
@@ -367,6 +368,10 @@ ret_t do_kexec_op(unsigned long op, XEN_GUEST_HANDLE(void) uarg)
|
||||
if ( !IS_PRIV(current->domain) )
|
||||
return -EPERM;
|
||||
|
||||
ret = xsm_kexec();
|
||||
if ( ret )
|
||||
return ret;
|
||||
|
||||
switch ( op )
|
||||
{
|
||||
case KEXEC_CMD_kexec_get_range:
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <asm/current.h>
|
||||
#include <asm/hardirq.h>
|
||||
#include <public/memory.h>
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
struct memop_args {
|
||||
/* INPUT */
|
||||
@@ -216,6 +217,7 @@ static long translate_gpfn_list(
|
||||
xen_pfn_t gpfn;
|
||||
xen_pfn_t mfn;
|
||||
struct domain *d;
|
||||
int rc;
|
||||
|
||||
if ( copy_from_guest(&op, uop, 1) )
|
||||
return -EFAULT;
|
||||
@@ -259,6 +261,13 @@ static long translate_gpfn_list(
|
||||
|
||||
mfn = gmfn_to_mfn(d, gpfn);
|
||||
|
||||
rc = xsm_translate_gpfn_list(current->domain, mfn);
|
||||
if ( rc )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if ( unlikely(__copy_to_guest_offset(op.mfn_list, i, &mfn, 1)) )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
@@ -538,6 +547,14 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg)
|
||||
return start_extent;
|
||||
args.domain = d;
|
||||
|
||||
rc = xsm_memory_adjust_reservation(current->domain, d);
|
||||
if ( rc )
|
||||
{
|
||||
if ( reservation.domid != DOMID_SELF )
|
||||
rcu_unlock_domain(d);
|
||||
return rc;
|
||||
}
|
||||
|
||||
switch ( op )
|
||||
{
|
||||
case XENMEM_increase_reservation:
|
||||
@@ -584,6 +601,14 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg)
|
||||
else if ( (d = rcu_lock_domain_by_id(domid)) == NULL )
|
||||
return -ESRCH;
|
||||
|
||||
rc = xsm_memory_stat_reservation(current->domain, d);
|
||||
if ( rc )
|
||||
{
|
||||
if ( domid != DOMID_SELF )
|
||||
rcu_unlock_domain(d);
|
||||
return rc;
|
||||
}
|
||||
|
||||
switch ( op )
|
||||
{
|
||||
case XENMEM_current_reservation:
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <xen/guest_access.h>
|
||||
#include <xen/multicall.h>
|
||||
#include <public/sched.h>
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
/* opt_sched: scheduler - default to credit */
|
||||
static char opt_sched[10] = "credit";
|
||||
@@ -461,6 +462,13 @@ ret_t do_sched_op(int cmd, XEN_GUEST_HANDLE(void) arg)
|
||||
if ( d == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_schedop_shutdown(current->domain, d);
|
||||
if ( ret )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* domain_pause() prevens any further execution in guest context. */
|
||||
domain_pause(d);
|
||||
domain_shutdown(d, (u8)sched_remote_shutdown.reason);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <public/sysctl.h>
|
||||
#include <asm/numa.h>
|
||||
#include <xen/nodemask.h>
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
extern long arch_do_sysctl(
|
||||
struct xen_sysctl *op, XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl);
|
||||
@@ -48,6 +49,10 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
|
||||
{
|
||||
case XEN_SYSCTL_readconsole:
|
||||
{
|
||||
ret = xsm_readconsole(op->u.readconsole.clear);
|
||||
if ( ret )
|
||||
break;
|
||||
|
||||
ret = read_console_ring(
|
||||
guest_handle_cast(op->u.readconsole.buffer, char),
|
||||
&op->u.readconsole.count,
|
||||
@@ -59,6 +64,10 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
|
||||
|
||||
case XEN_SYSCTL_tbuf_op:
|
||||
{
|
||||
ret = xsm_tbufcontrol();
|
||||
if ( ret )
|
||||
break;
|
||||
|
||||
ret = tb_control(&op->u.tbuf_op);
|
||||
if ( copy_to_guest(u_sysctl, op, 1) )
|
||||
ret = -EFAULT;
|
||||
@@ -67,6 +76,10 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
|
||||
|
||||
case XEN_SYSCTL_sched_id:
|
||||
{
|
||||
ret = xsm_sched_id();
|
||||
if ( ret )
|
||||
break;
|
||||
|
||||
op->u.sched_id.sched_id = sched_id();
|
||||
if ( copy_to_guest(u_sysctl, op, 1) )
|
||||
ret = -EFAULT;
|
||||
@@ -90,6 +103,10 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
|
||||
if ( num_domains == op->u.getdomaininfolist.max_domains )
|
||||
break;
|
||||
|
||||
ret = xsm_getdomaininfo(d);
|
||||
if ( ret )
|
||||
continue;
|
||||
|
||||
getdomaininfo(d, &info);
|
||||
|
||||
if ( copy_to_guest_offset(op->u.getdomaininfolist.buffer,
|
||||
@@ -117,6 +134,10 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
|
||||
#ifdef PERF_COUNTERS
|
||||
case XEN_SYSCTL_perfc_op:
|
||||
{
|
||||
ret = xsm_perfcontrol();
|
||||
if ( ret )
|
||||
break;
|
||||
|
||||
ret = perfc_control(&op->u.perfc_op);
|
||||
if ( copy_to_guest(u_sysctl, op, 1) )
|
||||
ret = -EFAULT;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <xen/sched.h>
|
||||
#include <public/xenoprof.h>
|
||||
#include <xen/paging.h>
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
/* Limit amount of pages used for shared buffer (per domain) */
|
||||
#define MAX_OPROF_SHARED_PAGES 32
|
||||
@@ -634,6 +635,10 @@ int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg)
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
ret = xsm_profile(current->domain, op);
|
||||
if ( ret )
|
||||
return ret;
|
||||
|
||||
spin_lock(&xenoprof_lock);
|
||||
|
||||
switch ( op )
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <asm/debugger.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/div64.h>
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
/* console: comma-separated list of console outputs. */
|
||||
static char opt_console[30] = OPT_CONSOLE_STR;
|
||||
@@ -358,6 +359,10 @@ long do_console_io(int cmd, int count, XEN_GUEST_HANDLE(char) buffer)
|
||||
return -EPERM;
|
||||
#endif
|
||||
|
||||
rc = xsm_console_io(current->domain, cmd);
|
||||
if ( rc )
|
||||
return rc;
|
||||
|
||||
switch ( cmd )
|
||||
{
|
||||
case CONSOLEIO_write:
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
#define __HYPERVISOR_sysctl 35
|
||||
#define __HYPERVISOR_domctl 36
|
||||
#define __HYPERVISOR_kexec_op 37
|
||||
#define __HYPERVISOR_xsm_op 38
|
||||
|
||||
/* Architecture-specific hypercall definitions. */
|
||||
#define __HYPERVISOR_arch_0 48
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <public/acm_ops.h>
|
||||
#include <public/event_channel.h>
|
||||
#include <asm/hypercall.h>
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
extern long
|
||||
do_ni_hypercall(
|
||||
@@ -125,4 +126,8 @@ compat_memory_op(
|
||||
|
||||
#endif
|
||||
|
||||
extern long
|
||||
do_xsm_op(
|
||||
XEN_GUEST_HANDLE(xsm_op_t) u_xsm_op);
|
||||
|
||||
#endif /* __XEN_HYPERCALL_H__ */
|
||||
@@ -0,0 +1,537 @@
|
||||
/*
|
||||
* This file contains the XSM hook definitions for Xen.
|
||||
*
|
||||
* This work is based on the LSM implementation in Linux 2.6.13.4.
|
||||
*
|
||||
* Author: George Coker, <gscoker@alpha.ncsc.mil>
|
||||
*
|
||||
* Contributors: Michael LeMay, <mdlemay@epoch.ncsc.mil>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __XSM_H__
|
||||
#define __XSM_H__
|
||||
|
||||
#include <xen/sched.h>
|
||||
#include <xen/multiboot.h>
|
||||
|
||||
typedef void xsm_op_t;
|
||||
DEFINE_XEN_GUEST_HANDLE(xsm_op_t);
|
||||
|
||||
extern long do_xsm_op (XEN_GUEST_HANDLE(xsm_op_t) op);
|
||||
|
||||
#ifdef XSM_ENABLE
|
||||
#define xsm_call(fn) xsm_ops->fn
|
||||
#else
|
||||
#define xsm_call(fn) 0
|
||||
#endif
|
||||
|
||||
/* policy magic number (defined by XSM_MAGIC) */
|
||||
typedef u32 xsm_magic_t;
|
||||
#ifndef XSM_MAGIC
|
||||
#define XSM_MAGIC 0x00000000
|
||||
#endif
|
||||
|
||||
#ifdef XSM_ENABLE
|
||||
|
||||
extern char *policy_buffer;
|
||||
extern u32 policy_size;
|
||||
|
||||
typedef int (*xsm_initcall_t)(void);
|
||||
|
||||
extern xsm_initcall_t __xsm_initcall_start[], __xsm_initcall_end[];
|
||||
|
||||
#define xsm_initcall(fn) \
|
||||
static xsm_initcall_t __initcall_##fn \
|
||||
__attribute_used__ __attribute__((__section__(".xsm_initcall.init"))) = fn
|
||||
|
||||
struct xsm_operations {
|
||||
void (*security_domaininfo) (struct domain *d,
|
||||
struct xen_domctl_getdomaininfo *info);
|
||||
int (*setvcpucontext) (struct domain *d);
|
||||
int (*pausedomain) (struct domain *d);
|
||||
int (*unpausedomain) (struct domain *d);
|
||||
int (*resumedomain) (struct domain *d);
|
||||
int (*domain_create) (struct domain *d, u32 ssidref);
|
||||
int (*max_vcpus) (struct domain *d);
|
||||
int (*destroydomain) (struct domain *d);
|
||||
int (*vcpuaffinity) (int cmd, struct domain *d);
|
||||
int (*scheduler) (struct domain *d);
|
||||
int (*getdomaininfo) (struct domain *d);
|
||||
int (*getvcpucontext) (struct domain *d);
|
||||
int (*getvcpuinfo) (struct domain *d);
|
||||
int (*domain_settime) (struct domain *d);
|
||||
int (*tbufcontrol) (void);
|
||||
int (*readconsole) (uint32_t clear);
|
||||
int (*sched_id) (void);
|
||||
int (*setdomainmaxmem) (struct domain *d);
|
||||
int (*setdomainhandle) (struct domain *d);
|
||||
int (*setdebugging) (struct domain *d);
|
||||
int (*irq_permission) (struct domain *d, uint8_t pirq, uint8_t access);
|
||||
int (*iomem_permission) (struct domain *d, unsigned long mfn,
|
||||
uint8_t access);
|
||||
int (*perfcontrol) (void);
|
||||
|
||||
int (*evtchn_unbound) (struct domain *d, struct evtchn *chn, domid_t id2);
|
||||
int (*evtchn_interdomain) (struct domain *d1, struct evtchn *chn1,
|
||||
struct domain *d2, struct evtchn *chn2);
|
||||
void (*evtchn_close_post) (struct evtchn *chn);
|
||||
int (*evtchn_send) (struct domain *d, struct evtchn *chn);
|
||||
int (*evtchn_status) (struct domain *d, struct evtchn *chn);
|
||||
int (*evtchn_reset) (struct domain *d1, struct domain *d2);
|
||||
|
||||
int (*grant_mapref) (struct domain *d1, struct domain *d2, uint32_t flags);
|
||||
int (*grant_unmapref) (struct domain *d1, struct domain *d2);
|
||||
int (*grant_setup) (struct domain *d1, struct domain *d2);
|
||||
int (*grant_transfer) (struct domain *d1, struct domain *d2);
|
||||
int (*grant_copy) (struct domain *d1, struct domain *d2);
|
||||
int (*grant_query_size) (struct domain *d1, struct domain *d2);
|
||||
|
||||
int (*alloc_security_domain) (struct domain *d);
|
||||
void (*free_security_domain) (struct domain *d);
|
||||
int (*alloc_security_evtchn) (struct evtchn *chn);
|
||||
void (*free_security_evtchn) (struct evtchn *chn);
|
||||
|
||||
int (*translate_gpfn_list) (struct domain *d, unsigned long mfn);
|
||||
int (*memory_adjust_reservation) (struct domain *d1, struct domain *d2);
|
||||
int (*memory_stat_reservation) (struct domain *d1, struct domain *d2);
|
||||
int (*memory_pin_page) (struct domain *d, struct page_info *page);
|
||||
int (*update_va_mapping) (struct domain *d, l1_pgentry_t pte);
|
||||
|
||||
int (*console_io) (struct domain *d, int cmd);
|
||||
|
||||
int (*profile) (struct domain *d, int op);
|
||||
|
||||
int (*kexec) (void);
|
||||
int (*schedop_shutdown) (struct domain *d1, struct domain *d2);
|
||||
|
||||
long (*__do_xsm_op) (XEN_GUEST_HANDLE(xsm_op_t) op);
|
||||
void (*complete_init) (struct domain *d);
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
int (*shadow_control) (struct domain *d, uint32_t op);
|
||||
int (*ioport_permission) (struct domain *d, uint32_t ioport,
|
||||
uint8_t access);
|
||||
int (*getpageframeinfo) (struct page_info *page);
|
||||
int (*getmemlist) (struct domain *d);
|
||||
int (*hypercall_init) (struct domain *d);
|
||||
int (*hvmcontext) (struct domain *d, uint32_t op);
|
||||
int (*address_size) (struct domain *d, uint32_t op);
|
||||
int (*hvm_param) (struct domain *d, unsigned long op);
|
||||
int (*hvm_set_pci_intx_level) (struct domain *d);
|
||||
int (*hvm_set_isa_irq_level) (struct domain *d);
|
||||
int (*hvm_set_pci_link_route) (struct domain *d);
|
||||
int (*apic) (struct domain *d, int cmd);
|
||||
int (*assign_vector) (struct domain *d, uint32_t pirq);
|
||||
int (*xen_settime) (void);
|
||||
int (*memtype) (uint32_t access);
|
||||
int (*microcode) (void);
|
||||
int (*physinfo) (void);
|
||||
int (*platform_quirk) (uint32_t);
|
||||
int (*machine_memory_map) (void);
|
||||
int (*domain_memory_map) (struct domain *d);
|
||||
int (*mmu_normal_update) (struct domain *d, intpte_t fpte);
|
||||
int (*mmu_machphys_update) (struct domain *d, unsigned long mfn);
|
||||
int (*add_to_physmap) (struct domain *d1, struct domain *d2);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
extern struct xsm_operations *xsm_ops;
|
||||
|
||||
static inline void xsm_security_domaininfo (struct domain *d,
|
||||
struct xen_domctl_getdomaininfo *info)
|
||||
{
|
||||
xsm_call(security_domaininfo(d, info));
|
||||
}
|
||||
|
||||
static inline int xsm_setvcpucontext(struct domain *d)
|
||||
{
|
||||
return xsm_call(setvcpucontext(d));
|
||||
}
|
||||
|
||||
static inline int xsm_pausedomain (struct domain *d)
|
||||
{
|
||||
return xsm_call(pausedomain(d));
|
||||
}
|
||||
|
||||
static inline int xsm_unpausedomain (struct domain *d)
|
||||
{
|
||||
return xsm_call(unpausedomain(d));
|
||||
}
|
||||
|
||||
static inline int xsm_resumedomain (struct domain *d)
|
||||
{
|
||||
return xsm_call(resumedomain(d));
|
||||
}
|
||||
|
||||
static inline int xsm_domain_create (struct domain *d, u32 ssidref)
|
||||
{
|
||||
return xsm_call(domain_create(d, ssidref));
|
||||
}
|
||||
|
||||
static inline int xsm_max_vcpus(struct domain *d)
|
||||
{
|
||||
return xsm_call(max_vcpus(d));
|
||||
}
|
||||
|
||||
static inline int xsm_destroydomain (struct domain *d)
|
||||
{
|
||||
return xsm_call(destroydomain(d));
|
||||
}
|
||||
|
||||
static inline int xsm_vcpuaffinity (int cmd, struct domain *d)
|
||||
{
|
||||
return xsm_call(vcpuaffinity(cmd, d));
|
||||
}
|
||||
|
||||
static inline int xsm_scheduler (struct domain *d)
|
||||
{
|
||||
return xsm_call(scheduler(d));
|
||||
}
|
||||
|
||||
static inline int xsm_getdomaininfo (struct domain *d)
|
||||
{
|
||||
return xsm_call(getdomaininfo(d));
|
||||
}
|
||||
|
||||
static inline int xsm_getvcpucontext (struct domain *d)
|
||||
{
|
||||
return xsm_call(getvcpucontext(d));
|
||||
}
|
||||
|
||||
static inline int xsm_getvcpuinfo (struct domain *d)
|
||||
{
|
||||
return xsm_call(getvcpuinfo(d));
|
||||
}
|
||||
|
||||
static inline int xsm_domain_settime (struct domain *d)
|
||||
{
|
||||
return xsm_call(domain_settime(d));
|
||||
}
|
||||
|
||||
static inline int xsm_tbufcontrol (void)
|
||||
{
|
||||
return xsm_call(tbufcontrol());
|
||||
}
|
||||
|
||||
static inline int xsm_readconsole (uint32_t clear)
|
||||
{
|
||||
return xsm_call(readconsole(clear));
|
||||
}
|
||||
|
||||
static inline int xsm_sched_id (void)
|
||||
{
|
||||
return xsm_call(sched_id());
|
||||
}
|
||||
|
||||
static inline int xsm_setdomainmaxmem (struct domain *d)
|
||||
{
|
||||
return xsm_call(setdomainmaxmem(d));
|
||||
}
|
||||
|
||||
static inline int xsm_setdomainhandle (struct domain *d)
|
||||
{
|
||||
return xsm_call(setdomainhandle(d));
|
||||
}
|
||||
|
||||
static inline int xsm_setdebugging (struct domain *d)
|
||||
{
|
||||
return xsm_call(setdebugging(d));
|
||||
}
|
||||
|
||||
static inline int xsm_irq_permission (struct domain *d, uint8_t pirq,
|
||||
uint8_t access)
|
||||
{
|
||||
return xsm_call(irq_permission(d, pirq, access));
|
||||
}
|
||||
|
||||
static inline int xsm_iomem_permission (struct domain *d, unsigned long mfn,
|
||||
uint8_t access)
|
||||
{
|
||||
return xsm_call(iomem_permission(d, mfn, access));
|
||||
}
|
||||
|
||||
static inline int xsm_perfcontrol (void)
|
||||
{
|
||||
return xsm_call(perfcontrol());
|
||||
}
|
||||
|
||||
static inline int xsm_evtchn_unbound (struct domain *d1, struct evtchn *chn,
|
||||
domid_t id2)
|
||||
{
|
||||
return xsm_call(evtchn_unbound(d1, chn, id2));
|
||||
}
|
||||
|
||||
static inline int xsm_evtchn_interdomain (struct domain *d1,
|
||||
struct evtchn *chan1, struct domain *d2, struct evtchn *chan2)
|
||||
{
|
||||
return xsm_call(evtchn_interdomain(d1, chan1, d2, chan2));
|
||||
}
|
||||
|
||||
static inline void xsm_evtchn_close_post (struct evtchn *chn)
|
||||
{
|
||||
xsm_call(evtchn_close_post(chn));
|
||||
}
|
||||
|
||||
static inline int xsm_evtchn_send (struct domain *d, struct evtchn *chn)
|
||||
{
|
||||
return xsm_call(evtchn_send(d, chn));
|
||||
}
|
||||
|
||||
static inline int xsm_evtchn_status (struct domain *d, struct evtchn *chn)
|
||||
{
|
||||
return xsm_call(evtchn_status(d, chn));
|
||||
}
|
||||
|
||||
static inline int xsm_evtchn_reset (struct domain *d1, struct domain *d2)
|
||||
{
|
||||
return xsm_call(evtchn_reset(d1, d2));
|
||||
}
|
||||
|
||||
static inline int xsm_grant_mapref (struct domain *d1, struct domain *d2,
|
||||
uint32_t flags)
|
||||
{
|
||||
return xsm_call(grant_mapref(d1, d2, flags));
|
||||
}
|
||||
|
||||
static inline int xsm_grant_unmapref (struct domain *d1, struct domain *d2)
|
||||
{
|
||||
return xsm_call(grant_unmapref(d1, d2));
|
||||
}
|
||||
|
||||
static inline int xsm_grant_setup (struct domain *d1, struct domain *d2)
|
||||
{
|
||||
return xsm_call(grant_setup(d1, d2));
|
||||
}
|
||||
|
||||
static inline int xsm_grant_transfer (struct domain *d1, struct domain *d2)
|
||||
{
|
||||
return xsm_call(grant_transfer(d1, d2));
|
||||
}
|
||||
|
||||
static inline int xsm_grant_copy (struct domain *d1, struct domain *d2)
|
||||
{
|
||||
return xsm_call(grant_copy(d1, d2));
|
||||
}
|
||||
|
||||
static inline int xsm_grant_query_size (struct domain *d1, struct domain *d2)
|
||||
{
|
||||
return xsm_call(grant_query_size(d1, d2));
|
||||
}
|
||||
|
||||
static inline int xsm_alloc_security_domain (struct domain *d)
|
||||
{
|
||||
return xsm_call(alloc_security_domain(d));
|
||||
}
|
||||
|
||||
static inline void xsm_free_security_domain (struct domain *d)
|
||||
{
|
||||
xsm_call(free_security_domain(d));
|
||||
}
|
||||
|
||||
static inline int xsm_alloc_security_evtchn (struct evtchn *chn)
|
||||
{
|
||||
return xsm_call(alloc_security_evtchn(chn));
|
||||
}
|
||||
|
||||
static inline void xsm_free_security_evtchn (struct evtchn *chn)
|
||||
{
|
||||
xsm_call(free_security_evtchn(chn));
|
||||
}
|
||||
|
||||
static inline int xsm_translate_gpfn_list (struct domain *d, unsigned long mfn)
|
||||
{
|
||||
return xsm_call(translate_gpfn_list(d, mfn));
|
||||
}
|
||||
|
||||
static inline int xsm_memory_adjust_reservation (struct domain *d1, struct
|
||||
domain *d2)
|
||||
{
|
||||
return xsm_call(memory_adjust_reservation(d1, d2));
|
||||
}
|
||||
|
||||
static inline int xsm_memory_stat_reservation (struct domain *d1,
|
||||
struct domain *d2)
|
||||
{
|
||||
return xsm_call(memory_stat_reservation(d1, d2));
|
||||
}
|
||||
|
||||
static inline int xsm_memory_pin_page(struct domain *d, struct page_info *page)
|
||||
{
|
||||
return xsm_call(memory_pin_page(d, page));
|
||||
}
|
||||
|
||||
static inline int xsm_update_va_mapping(struct domain *d, l1_pgentry_t pte)
|
||||
{
|
||||
return xsm_call(update_va_mapping(d, pte));
|
||||
}
|
||||
|
||||
static inline int xsm_console_io (struct domain *d, int cmd)
|
||||
{
|
||||
return xsm_call(console_io(d, cmd));
|
||||
}
|
||||
|
||||
static inline int xsm_profile (struct domain *d, int op)
|
||||
{
|
||||
return xsm_call(profile(d, op));
|
||||
}
|
||||
|
||||
static inline int xsm_kexec (void)
|
||||
{
|
||||
return xsm_call(kexec());
|
||||
}
|
||||
|
||||
static inline int xsm_schedop_shutdown (struct domain *d1, struct domain *d2)
|
||||
{
|
||||
return xsm_call(schedop_shutdown(d1, d2));
|
||||
}
|
||||
|
||||
static inline long __do_xsm_op (XEN_GUEST_HANDLE(xsm_op_t) op)
|
||||
{
|
||||
return xsm_call(__do_xsm_op(op));
|
||||
}
|
||||
|
||||
static inline void xsm_complete_init (struct domain *d)
|
||||
{
|
||||
xsm_call(complete_init(d));
|
||||
}
|
||||
|
||||
#ifdef XSM_ENABLE
|
||||
extern int xsm_init(unsigned int *initrdidx, const multiboot_info_t *mbi,
|
||||
unsigned long initial_images_start);
|
||||
extern int xsm_policy_init(unsigned int *initrdidx, const multiboot_info_t *mbi,
|
||||
unsigned long initial_images_start);
|
||||
extern int register_xsm(struct xsm_operations *ops);
|
||||
extern int unregister_xsm(struct xsm_operations *ops);
|
||||
#else
|
||||
static inline int xsm_init (unsigned int *initrdidx,
|
||||
const multiboot_info_t *mbi, unsigned long initial_images_start)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
static inline int xsm_shadow_control (struct domain *d, uint32_t op)
|
||||
{
|
||||
return xsm_call(shadow_control(d, op));
|
||||
}
|
||||
|
||||
static inline int xsm_ioport_permission (struct domain *d, uint32_t ioport,
|
||||
uint8_t access)
|
||||
{
|
||||
return xsm_call(ioport_permission(d, ioport, access));
|
||||
}
|
||||
|
||||
static inline int xsm_getpageframeinfo (struct page_info *page)
|
||||
{
|
||||
return xsm_call(getpageframeinfo(page));
|
||||
}
|
||||
|
||||
static inline int xsm_getmemlist (struct domain *d)
|
||||
{
|
||||
return xsm_call(getmemlist(d));
|
||||
}
|
||||
|
||||
static inline int xsm_hypercall_init (struct domain *d)
|
||||
{
|
||||
return xsm_call(hypercall_init(d));
|
||||
}
|
||||
|
||||
static inline int xsm_hvmcontext (struct domain *d, uint32_t cmd)
|
||||
{
|
||||
return xsm_call(hvmcontext(d, cmd));
|
||||
}
|
||||
|
||||
static inline int xsm_address_size (struct domain *d, uint32_t cmd)
|
||||
{
|
||||
return xsm_call(address_size(d, cmd));
|
||||
}
|
||||
|
||||
static inline int xsm_hvm_param (struct domain *d, unsigned long op)
|
||||
{
|
||||
return xsm_call(hvm_param(d, op));
|
||||
}
|
||||
|
||||
static inline int xsm_hvm_set_pci_intx_level (struct domain *d)
|
||||
{
|
||||
return xsm_call(hvm_set_pci_intx_level(d));
|
||||
}
|
||||
|
||||
static inline int xsm_hvm_set_isa_irq_level (struct domain *d)
|
||||
{
|
||||
return xsm_call(hvm_set_isa_irq_level(d));
|
||||
}
|
||||
|
||||
static inline int xsm_hvm_set_pci_link_route (struct domain *d)
|
||||
{
|
||||
return xsm_call(hvm_set_pci_link_route(d));
|
||||
}
|
||||
|
||||
static inline int xsm_apic (struct domain *d, int cmd)
|
||||
{
|
||||
return xsm_call(apic(d, cmd));
|
||||
}
|
||||
|
||||
static inline int xsm_assign_vector (struct domain *d, uint32_t pirq)
|
||||
{
|
||||
return xsm_call(assign_vector(d, pirq));
|
||||
}
|
||||
|
||||
static inline int xsm_xen_settime (void)
|
||||
{
|
||||
return xsm_call(xen_settime());
|
||||
}
|
||||
|
||||
static inline int xsm_memtype (uint32_t access)
|
||||
{
|
||||
return xsm_call(memtype(access));
|
||||
}
|
||||
|
||||
static inline int xsm_microcode (void)
|
||||
{
|
||||
return xsm_call(microcode());
|
||||
}
|
||||
|
||||
static inline int xsm_physinfo (void)
|
||||
{
|
||||
return xsm_call(physinfo());
|
||||
}
|
||||
|
||||
static inline int xsm_platform_quirk (uint32_t quirk)
|
||||
{
|
||||
return xsm_call(platform_quirk(quirk));
|
||||
}
|
||||
|
||||
static inline int xsm_machine_memory_map(void)
|
||||
{
|
||||
return xsm_call(machine_memory_map());
|
||||
}
|
||||
|
||||
static inline int xsm_domain_memory_map(struct domain *d)
|
||||
{
|
||||
return xsm_call(domain_memory_map(d));
|
||||
}
|
||||
|
||||
static inline int xsm_mmu_normal_update (struct domain *d, intpte_t fpte)
|
||||
{
|
||||
return xsm_call(mmu_normal_update(d, fpte));
|
||||
}
|
||||
|
||||
static inline int xsm_mmu_machphys_update (struct domain *d, unsigned long mfn)
|
||||
{
|
||||
return xsm_call(mmu_machphys_update(d, mfn));
|
||||
}
|
||||
|
||||
static inline int xsm_add_to_physmap(struct domain *d1, struct domain *d2)
|
||||
{
|
||||
return xsm_call(add_to_physmap(d1, d2));
|
||||
}
|
||||
#endif /* CONFIG_X86 */
|
||||
|
||||
#endif /* __XSM_H */
|
||||
@@ -0,0 +1,5 @@
|
||||
obj-y += xsm_core.o
|
||||
obj-y += xsm_policy.o
|
||||
ifeq ($(XSM_ENABLE),y)
|
||||
obj-y += dummy.o
|
||||
endif
|
||||
+488
@@ -0,0 +1,488 @@
|
||||
/*
|
||||
* This work is based on the LSM implementation in Linux 2.6.13.4.
|
||||
*
|
||||
* Author: George Coker, <gscoker@alpha.ncsc.mil>
|
||||
*
|
||||
* Contributors: Michael LeMay, <mdlemay@epoch.ncsc.mil>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <xen/sched.h>
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
static void dummy_security_domaininfo(struct domain *d,
|
||||
struct xen_domctl_getdomaininfo *info)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static int dummy_setvcpucontext(struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_pausedomain (struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_unpausedomain (struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_resumedomain (struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_domain_create(struct domain *d, u32 ssidref)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_max_vcpus(struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_destroydomain (struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_vcpuaffinity (int cmd, struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_scheduler (struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_getdomaininfo (struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_getvcpucontext (struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_getvcpuinfo (struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_domain_settime (struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_tbufcontrol (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_readconsole (uint32_t clear)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_sched_id (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_setdomainmaxmem (struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_setdomainhandle (struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_setdebugging (struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_irq_permission (struct domain *d, uint8_t pirq, uint8_t access)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_iomem_permission (struct domain *d, unsigned long mfn,
|
||||
uint8_t access)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_perfcontrol (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_alloc_security_domain (struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dummy_free_security_domain (struct domain *d)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static int dummy_grant_mapref (struct domain *d1, struct domain *d2,
|
||||
uint32_t flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_grant_unmapref (struct domain *d1, struct domain *d2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_grant_setup (struct domain *d1, struct domain *d2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_grant_transfer (struct domain *d1, struct domain *d2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_grant_copy (struct domain *d1, struct domain *d2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_grant_query_size (struct domain *d1, struct domain *d2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_translate_gpfn_list (struct domain *d, unsigned long mfn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_memory_adjust_reservation (struct domain *d1,
|
||||
struct domain *d2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_memory_stat_reservation (struct domain *d1, struct domain *d2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_update_va_mapping (struct domain *d, l1_pgentry_t pte)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_console_io (struct domain *d, int cmd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_profile (struct domain *d, int op)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_kexec (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_schedop_shutdown (struct domain *d1, struct domain *d2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_memory_pin_page(struct domain *d, struct page_info *page)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_evtchn_unbound (struct domain *d, struct evtchn *chn,
|
||||
domid_t id2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_evtchn_interdomain (struct domain *d1, struct evtchn
|
||||
*chan1, struct domain *d2, struct evtchn *chan2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dummy_evtchn_close_post (struct evtchn *chn)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static int dummy_evtchn_send (struct domain *d, struct evtchn *chn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_evtchn_status (struct domain *d, struct evtchn *chn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_evtchn_reset (struct domain *d1, struct domain *d2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_alloc_security_evtchn (struct evtchn *chn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dummy_free_security_evtchn (struct evtchn *chn)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void dummy_complete_init (struct domain *d)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static long dummy___do_xsm_op(XEN_GUEST_HANDLE(xsm_op_t) op)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
static int dummy_shadow_control (struct domain *d, uint32_t op)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_ioport_permission (struct domain *d, uint32_t ioport,
|
||||
uint8_t access)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_getpageframeinfo (struct page_info *page)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_getmemlist (struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_hypercall_init (struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_hvmcontext (struct domain *d, uint32_t cmd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_address_size (struct domain *d, uint32_t cmd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_hvm_param (struct domain *d, unsigned long op)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_hvm_set_pci_intx_level (struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_hvm_set_isa_irq_level (struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_hvm_set_pci_link_route (struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_apic (struct domain *d, int cmd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_assign_vector (struct domain *d, uint32_t pirq)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_xen_settime (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_memtype (uint32_t access)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_microcode (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_physinfo (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_platform_quirk (uint32_t quirk)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_machine_memory_map (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_domain_memory_map (struct domain *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_mmu_normal_update (struct domain *d, intpte_t fpte)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_mmu_machphys_update (struct domain *d, unsigned long mfn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_add_to_physmap (struct domain *d1, struct domain *d2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct xsm_operations dummy_xsm_ops;
|
||||
|
||||
#define set_to_dummy_if_null(ops, function) \
|
||||
do { \
|
||||
if ( !ops->function ) \
|
||||
{ \
|
||||
ops->function = dummy_##function; \
|
||||
dprintk(XENLOG_DEBUG, "Had to override the " #function \
|
||||
" security operation with the dummy one.\n"); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
void xsm_fixup_ops (struct xsm_operations *ops)
|
||||
{
|
||||
set_to_dummy_if_null(ops, security_domaininfo);
|
||||
set_to_dummy_if_null(ops, setvcpucontext);
|
||||
set_to_dummy_if_null(ops, pausedomain);
|
||||
set_to_dummy_if_null(ops, unpausedomain);
|
||||
set_to_dummy_if_null(ops, resumedomain);
|
||||
set_to_dummy_if_null(ops, domain_create);
|
||||
set_to_dummy_if_null(ops, max_vcpus);
|
||||
set_to_dummy_if_null(ops, destroydomain);
|
||||
set_to_dummy_if_null(ops, vcpuaffinity);
|
||||
set_to_dummy_if_null(ops, scheduler);
|
||||
set_to_dummy_if_null(ops, getdomaininfo);
|
||||
set_to_dummy_if_null(ops, getvcpucontext);
|
||||
set_to_dummy_if_null(ops, getvcpuinfo);
|
||||
set_to_dummy_if_null(ops, domain_settime);
|
||||
set_to_dummy_if_null(ops, tbufcontrol);
|
||||
set_to_dummy_if_null(ops, readconsole);
|
||||
set_to_dummy_if_null(ops, sched_id);
|
||||
set_to_dummy_if_null(ops, setdomainmaxmem);
|
||||
set_to_dummy_if_null(ops, setdomainhandle);
|
||||
set_to_dummy_if_null(ops, setdebugging);
|
||||
set_to_dummy_if_null(ops, irq_permission);
|
||||
set_to_dummy_if_null(ops, iomem_permission);
|
||||
set_to_dummy_if_null(ops, perfcontrol);
|
||||
|
||||
set_to_dummy_if_null(ops, evtchn_unbound);
|
||||
set_to_dummy_if_null(ops, evtchn_interdomain);
|
||||
set_to_dummy_if_null(ops, evtchn_close_post);
|
||||
set_to_dummy_if_null(ops, evtchn_send);
|
||||
set_to_dummy_if_null(ops, evtchn_status);
|
||||
set_to_dummy_if_null(ops, evtchn_reset);
|
||||
|
||||
set_to_dummy_if_null(ops, grant_mapref);
|
||||
set_to_dummy_if_null(ops, grant_unmapref);
|
||||
set_to_dummy_if_null(ops, grant_setup);
|
||||
set_to_dummy_if_null(ops, grant_transfer);
|
||||
set_to_dummy_if_null(ops, grant_copy);
|
||||
set_to_dummy_if_null(ops, grant_query_size);
|
||||
|
||||
set_to_dummy_if_null(ops, alloc_security_domain);
|
||||
set_to_dummy_if_null(ops, free_security_domain);
|
||||
set_to_dummy_if_null(ops, alloc_security_evtchn);
|
||||
set_to_dummy_if_null(ops, free_security_evtchn);
|
||||
|
||||
set_to_dummy_if_null(ops, translate_gpfn_list);
|
||||
set_to_dummy_if_null(ops, memory_adjust_reservation);
|
||||
set_to_dummy_if_null(ops, memory_stat_reservation);
|
||||
set_to_dummy_if_null(ops, memory_pin_page);
|
||||
set_to_dummy_if_null(ops, update_va_mapping);
|
||||
|
||||
set_to_dummy_if_null(ops, console_io);
|
||||
|
||||
set_to_dummy_if_null(ops, profile);
|
||||
|
||||
set_to_dummy_if_null(ops, kexec);
|
||||
set_to_dummy_if_null(ops, schedop_shutdown);
|
||||
|
||||
set_to_dummy_if_null(ops, __do_xsm_op);
|
||||
set_to_dummy_if_null(ops, complete_init);
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
set_to_dummy_if_null(ops, shadow_control);
|
||||
set_to_dummy_if_null(ops, ioport_permission);
|
||||
set_to_dummy_if_null(ops, getpageframeinfo);
|
||||
set_to_dummy_if_null(ops, getmemlist);
|
||||
set_to_dummy_if_null(ops, hypercall_init);
|
||||
set_to_dummy_if_null(ops, hvmcontext);
|
||||
set_to_dummy_if_null(ops, address_size);
|
||||
set_to_dummy_if_null(ops, hvm_param);
|
||||
set_to_dummy_if_null(ops, hvm_set_pci_intx_level);
|
||||
set_to_dummy_if_null(ops, hvm_set_isa_irq_level);
|
||||
set_to_dummy_if_null(ops, hvm_set_pci_link_route);
|
||||
set_to_dummy_if_null(ops, apic);
|
||||
set_to_dummy_if_null(ops, assign_vector);
|
||||
set_to_dummy_if_null(ops, xen_settime);
|
||||
set_to_dummy_if_null(ops, memtype);
|
||||
set_to_dummy_if_null(ops, microcode);
|
||||
set_to_dummy_if_null(ops, physinfo);
|
||||
set_to_dummy_if_null(ops, platform_quirk);
|
||||
set_to_dummy_if_null(ops, machine_memory_map);
|
||||
set_to_dummy_if_null(ops, domain_memory_map);
|
||||
set_to_dummy_if_null(ops, mmu_normal_update);
|
||||
set_to_dummy_if_null(ops, mmu_machphys_update);
|
||||
set_to_dummy_if_null(ops, add_to_physmap);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* This work is based on the LSM implementation in Linux 2.6.13.4.
|
||||
*
|
||||
* Author: George Coker, <gscoker@alpha.ncsc.mil>
|
||||
*
|
||||
* Contributors: Michael LeMay, <mdlemay@epoch.ncsc.mil>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <xen/init.h>
|
||||
#include <xen/errno.h>
|
||||
#include <xen/lib.h>
|
||||
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
#ifdef XSM_ENABLE
|
||||
|
||||
#define XSM_FRAMEWORK_VERSION "1.0.0"
|
||||
|
||||
extern struct xsm_operations dummy_xsm_ops;
|
||||
extern void xsm_fixup_ops(struct xsm_operations *ops);
|
||||
|
||||
struct xsm_operations *xsm_ops;
|
||||
|
||||
static inline int verify(struct xsm_operations *ops)
|
||||
{
|
||||
/* verify the security_operations structure exists */
|
||||
if ( !ops )
|
||||
return -EINVAL;
|
||||
xsm_fixup_ops(ops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init do_xsm_initcalls(void)
|
||||
{
|
||||
xsm_initcall_t *call;
|
||||
call = __xsm_initcall_start;
|
||||
while ( call < __xsm_initcall_end )
|
||||
{
|
||||
(*call) ();
|
||||
call++;
|
||||
}
|
||||
}
|
||||
|
||||
int __init xsm_init(unsigned int *initrdidx, const multiboot_info_t *mbi,
|
||||
unsigned long initial_images_start)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
printk("XSM Framework v" XSM_FRAMEWORK_VERSION " initialized\n");
|
||||
|
||||
if ( XSM_MAGIC )
|
||||
{
|
||||
ret = xsm_policy_init(initrdidx, mbi, initial_images_start);
|
||||
if ( ret )
|
||||
{
|
||||
printk("%s: Error initializing policy.\n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if ( verify(&dummy_xsm_ops) )
|
||||
{
|
||||
printk("%s could not verify "
|
||||
"dummy_xsm_ops structure.\n", __FUNCTION__);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
xsm_ops = &dummy_xsm_ops;
|
||||
do_xsm_initcalls();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int register_xsm(struct xsm_operations *ops)
|
||||
{
|
||||
if ( verify(ops) )
|
||||
{
|
||||
printk("%s could not verify "
|
||||
"security_operations structure.\n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ( xsm_ops != &dummy_xsm_ops )
|
||||
return -EAGAIN;
|
||||
|
||||
xsm_ops = ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int unregister_xsm(struct xsm_operations *ops)
|
||||
{
|
||||
if ( ops != xsm_ops )
|
||||
{
|
||||
printk("%s: trying to unregister "
|
||||
"a security_opts structure that is not "
|
||||
"registered, failing.\n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
xsm_ops = &dummy_xsm_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
long do_xsm_op (XEN_GUEST_HANDLE(xsm_op_t) op)
|
||||
{
|
||||
return __do_xsm_op(op);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Authors:
|
||||
* Reiner Sailer, <sailer@watson.ibm.com>
|
||||
* Stefan Berger, <stefanb@watson.ibm.com>
|
||||
*
|
||||
* Contributors:
|
||||
* Michael LeMay, <mdlemay@epoch.ncsc.mil>
|
||||
* George Coker, <gscoker@alpha.ncsc.mil>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
*
|
||||
* This file contains the XSM policy init functions for Xen.
|
||||
* This file is based on the ACM functions of the same name.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <xsm/xsm.h>
|
||||
#include <xen/multiboot.h>
|
||||
|
||||
char *policy_buffer = NULL;
|
||||
u32 policy_size = 0;
|
||||
|
||||
int xsm_policy_init(unsigned int *initrdidx, const multiboot_info_t *mbi,
|
||||
unsigned long initial_images_start)
|
||||
{
|
||||
int i;
|
||||
module_t *mod = (module_t *)__va(mbi->mods_addr);
|
||||
int rc = 0;
|
||||
u32 *_policy_start;
|
||||
unsigned long start, _policy_len;
|
||||
|
||||
/*
|
||||
* Try all modules and see whichever could be the binary policy.
|
||||
* Adjust the initrdidx if module[1] is the binary policy.
|
||||
*/
|
||||
for ( i = mbi->mods_count-1; i >= 1; i-- )
|
||||
{
|
||||
start = initial_images_start + (mod[i].mod_start-mod[0].mod_start);
|
||||
#if defined(__i386__)
|
||||
_policy_start = (u32 *)start;
|
||||
#elif defined(__x86_64__)
|
||||
_policy_start = maddr_to_virt(start);
|
||||
#endif
|
||||
_policy_len = mod[i].mod_end - mod[i].mod_start;
|
||||
|
||||
if ( (xsm_magic_t)(*_policy_start) == XSM_MAGIC )
|
||||
{
|
||||
policy_buffer = (char *)_policy_start;
|
||||
policy_size = _policy_len;
|
||||
|
||||
printk("Policy len 0x%lx, start at %p.\n",
|
||||
_policy_len,_policy_start);
|
||||
|
||||
if ( i == 1 )
|
||||
*initrdidx = (mbi->mods_count > 2) ? 2 : 0;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||