mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
Merging with xen-unstable
This commit is contained in:
commit
31dfa31bc0
46 files changed
+2617
-1588
No files matched your search
@@ -86,6 +86,8 @@
|
||||
^tools/check/\..*$
|
||||
^tools/cmdline/.*$
|
||||
^tools/cmdline/xen/.*$
|
||||
^tools/consoled/consoled$
|
||||
^tools/consoled/xc_console$
|
||||
^tools/debugger/pdb/pdb$
|
||||
^tools/debugger/pdb/linux-[0-9.]*-module/.*\.ko$
|
||||
^tools/debugger/pdb/linux-[0-9.]*-module/.*\.mod.c$
|
||||
@@ -128,8 +130,8 @@
|
||||
^tools/misc/xc_shadow$
|
||||
^tools/misc/xen_cpuperf$
|
||||
^tools/misc/xenperf$
|
||||
^tools/policy/policy_tool$
|
||||
^tools/policy/xen/.*$
|
||||
^tools/security/secpol_tool$
|
||||
^tools/security/xen/.*$
|
||||
^tools/pygrub/build/.*$
|
||||
^tools/python/build/.*$
|
||||
^tools/tests/test_x86_emulator$
|
||||
|
||||
@@ -18,8 +18,8 @@ CONFIG_XEN_BLKDEV_GRANT=y
|
||||
CONFIG_XEN_NETDEV_BACKEND=y
|
||||
CONFIG_XEN_BLKDEV_FRONTEND=y
|
||||
CONFIG_XEN_NETDEV_FRONTEND=y
|
||||
CONFIG_XEN_NETDEV_GRANT_TX=y
|
||||
CONFIG_XEN_NETDEV_GRANT_RX=y
|
||||
#CONFIG_XEN_NETDEV_GRANT_TX=y
|
||||
#CONFIG_XEN_NETDEV_GRANT_RX=y
|
||||
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
|
||||
# CONFIG_XEN_BLKDEV_TAP is not set
|
||||
# CONFIG_XEN_SHADOW_MODE is not set
|
||||
|
||||
@@ -15,8 +15,8 @@ CONFIG_NO_IDLE_HZ=y
|
||||
CONFIG_XEN_BLKDEV_GRANT=y
|
||||
CONFIG_XEN_BLKDEV_FRONTEND=y
|
||||
CONFIG_XEN_NETDEV_FRONTEND=y
|
||||
CONFIG_XEN_NETDEV_GRANT_TX=y
|
||||
CONFIG_XEN_NETDEV_GRANT_RX=y
|
||||
#CONFIG_XEN_NETDEV_GRANT_TX=y
|
||||
#CONFIG_XEN_NETDEV_GRANT_RX=y
|
||||
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
|
||||
# CONFIG_XEN_BLKDEV_TAP is not set
|
||||
# CONFIG_XEN_SHADOW_MODE is not set
|
||||
|
||||
@@ -204,6 +204,63 @@ static inline int is_prefetch(struct pt_regs *regs, unsigned long addr,
|
||||
|
||||
fastcall void do_invalid_op(struct pt_regs *, unsigned long);
|
||||
|
||||
#ifdef CONFIG_X86_PAE
|
||||
static void dump_fault_path(unsigned long address)
|
||||
{
|
||||
unsigned long *p, page;
|
||||
|
||||
page = __pa(per_cpu(cur_pgd, smp_processor_id()));
|
||||
p = (unsigned long *)__va(page);
|
||||
p += (address >> 30) * 2;
|
||||
printk(KERN_ALERT "%08lx -> *pde = %08lx:%08lx\n", page, p[1], p[0]);
|
||||
if (p[0] & 1) {
|
||||
page = p[0] & PAGE_MASK;
|
||||
address &= 0x3fffffff;
|
||||
page = machine_to_phys(page);
|
||||
p = (unsigned long *)__va(page);
|
||||
p += (address >> 21) * 2;
|
||||
printk(KERN_ALERT "%08lx -> *pme = %08lx:%08lx\n", page, p[1], p[0]);
|
||||
#ifndef CONFIG_HIGHPTE
|
||||
if (p[0] & 1) {
|
||||
page = p[0] & PAGE_MASK;
|
||||
address &= 0x001fffff;
|
||||
page = machine_to_phys(page);
|
||||
p = (unsigned long *) __va(page);
|
||||
p += (address >> 12) * 2;
|
||||
printk(KERN_ALERT "%08lx -> *pte = %08lx:%08lx\n", page, p[1], p[0]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void dump_fault_path(unsigned long address)
|
||||
{
|
||||
unsigned long page;
|
||||
|
||||
page = ((unsigned long *) per_cpu(cur_pgd, smp_processor_id()))
|
||||
[address >> 22];
|
||||
printk(KERN_ALERT "*pde = ma %08lx pa %08lx\n", page,
|
||||
machine_to_phys(page));
|
||||
/*
|
||||
* We must not directly access the pte in the highpte
|
||||
* case, the page table might be allocated in highmem.
|
||||
* And lets rather not kmap-atomic the pte, just in case
|
||||
* it's allocated already.
|
||||
*/
|
||||
#ifndef CONFIG_HIGHPTE
|
||||
if (page & 1) {
|
||||
page &= PAGE_MASK;
|
||||
address &= 0x003ff000;
|
||||
page = machine_to_phys(page);
|
||||
page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
|
||||
printk(KERN_ALERT "*pte = ma %08lx pa %08lx\n", page,
|
||||
machine_to_phys(page));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* This routine handles page faults. It determines the address,
|
||||
* and the problem, and then passes it off to one of the appropriate
|
||||
@@ -220,7 +277,6 @@ fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code,
|
||||
struct task_struct *tsk;
|
||||
struct mm_struct *mm;
|
||||
struct vm_area_struct * vma;
|
||||
unsigned long page;
|
||||
int write;
|
||||
siginfo_t info;
|
||||
|
||||
@@ -454,26 +510,7 @@ no_context:
|
||||
printk(" at virtual address %08lx\n",address);
|
||||
printk(KERN_ALERT " printing eip:\n");
|
||||
printk("%08lx\n", regs->eip);
|
||||
page = ((unsigned long *) per_cpu(cur_pgd, smp_processor_id()))
|
||||
[address >> 22];
|
||||
printk(KERN_ALERT "*pde = ma %08lx pa %08lx\n", page,
|
||||
machine_to_phys(page));
|
||||
/*
|
||||
* We must not directly access the pte in the highpte
|
||||
* case, the page table might be allocated in highmem.
|
||||
* And lets rather not kmap-atomic the pte, just in case
|
||||
* it's allocated already.
|
||||
*/
|
||||
#ifndef CONFIG_HIGHPTE
|
||||
if (page & 1) {
|
||||
page &= PAGE_MASK;
|
||||
address &= 0x003ff000;
|
||||
page = machine_to_phys(page);
|
||||
page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
|
||||
printk(KERN_ALERT "*pte = ma %08lx pa %08lx\n", page,
|
||||
machine_to_phys(page));
|
||||
}
|
||||
#endif
|
||||
dump_fault_path(address);
|
||||
die("Oops", regs, error_code);
|
||||
bust_spinlocks(0);
|
||||
do_exit(SIGKILL);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*
|
||||
* Copyright (c) 2003, B Dragovic
|
||||
* Copyright (c) 2003-2004, M Williamson, K Fraser
|
||||
* Copyright (c) 2005 Dan M. Smith, IBM Corporation
|
||||
*
|
||||
* This file may be distributed separately from the Linux kernel, or
|
||||
* incorporated into other software packages, subject to the following license:
|
||||
@@ -42,7 +43,6 @@
|
||||
#include <linux/vmalloc.h>
|
||||
#include <asm-xen/xen_proc.h>
|
||||
#include <asm-xen/hypervisor.h>
|
||||
#include <asm-xen/ctrl_if.h>
|
||||
#include <asm-xen/balloon.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/pgtable.h>
|
||||
@@ -50,6 +50,10 @@
|
||||
#include <asm/tlb.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
#include<asm-xen/xenbus.h>
|
||||
|
||||
#define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
|
||||
|
||||
static struct proc_dir_entry *balloon_pde;
|
||||
|
||||
static DECLARE_MUTEX(balloon_mutex);
|
||||
@@ -77,11 +81,17 @@ static void balloon_process(void *unused);
|
||||
static DECLARE_WORK(balloon_worker, balloon_process, NULL);
|
||||
static struct timer_list balloon_timer;
|
||||
|
||||
/* Flag for dom0 xenstore workaround */
|
||||
static int balloon_xenbus_init=0;
|
||||
|
||||
/* Init Function */
|
||||
void balloon_init_watcher(void);
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
||||
/* Use the private and mapping fields of struct page as a list. */
|
||||
#define PAGE_TO_LIST(p) ( (struct list_head *)&p->private )
|
||||
#define LIST_TO_PAGE(l) ( list_entry( ((unsigned long *)l), \
|
||||
struct page, private ) )
|
||||
struct page, private ) )
|
||||
#define UNLIST_PAGE(p) do { list_del(PAGE_TO_LIST(p)); \
|
||||
p->mapping = NULL; \
|
||||
p->private = 0; } while(0)
|
||||
@@ -297,26 +307,97 @@ static void set_new_target(unsigned long target)
|
||||
schedule_work(&balloon_worker);
|
||||
}
|
||||
|
||||
static void balloon_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
|
||||
static struct xenbus_watch xb_watch =
|
||||
{
|
||||
switch ( msg->subtype )
|
||||
{
|
||||
case CMSG_MEM_REQUEST_SET:
|
||||
{
|
||||
mem_request_t *req = (mem_request_t *)&msg->msg[0];
|
||||
set_new_target(req->target);
|
||||
req->status = 0;
|
||||
}
|
||||
break;
|
||||
.node = "memory"
|
||||
};
|
||||
|
||||
default:
|
||||
msg->length = 0;
|
||||
break;
|
||||
/* FIXME: This is part of a dom0 sequencing workaround */
|
||||
static struct xenbus_watch root_watch =
|
||||
{
|
||||
.node = "/"
|
||||
};
|
||||
|
||||
/* React to a change in the target key */
|
||||
static void watch_target(struct xenbus_watch *watch, const char *node)
|
||||
{
|
||||
unsigned long new_target;
|
||||
int err;
|
||||
|
||||
if(watch == &root_watch)
|
||||
{
|
||||
/* FIXME: This is part of a dom0 sequencing workaround */
|
||||
if(register_xenbus_watch(&xb_watch) == 0)
|
||||
{
|
||||
/*
|
||||
We successfully set a watch on memory/target:
|
||||
now we can stop watching root
|
||||
*/
|
||||
unregister_xenbus_watch(&root_watch);
|
||||
balloon_xenbus_init=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ctrl_if_send_response(msg);
|
||||
err = xenbus_scanf("memory", "target", "%lu", &new_target);
|
||||
|
||||
if(err != 1)
|
||||
{
|
||||
IPRINTK("Unable to read memory/target\n");
|
||||
return;
|
||||
}
|
||||
|
||||
set_new_target(new_target >> PAGE_SHIFT);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Try to set up our watcher, if not already set
|
||||
|
||||
*/
|
||||
void balloon_init_watcher(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
if(!xen_start_info.store_evtchn)
|
||||
{
|
||||
IPRINTK("Delaying watcher init until xenstore is available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
down(&xenbus_lock);
|
||||
|
||||
if(! balloon_xenbus_init)
|
||||
{
|
||||
err = register_xenbus_watch(&xb_watch);
|
||||
if(err)
|
||||
{
|
||||
/* BIG FAT FIXME: dom0 sequencing workaround
|
||||
* dom0 can't set a watch on memory/target until
|
||||
* after the tools create it. So, we have to watch
|
||||
* the whole store until that happens.
|
||||
*
|
||||
* This will go away when we have the ability to watch
|
||||
* non-existant keys
|
||||
*/
|
||||
register_xenbus_watch(&root_watch);
|
||||
}
|
||||
else
|
||||
{
|
||||
IPRINTK("Balloon xenbus watcher initialized\n");
|
||||
balloon_xenbus_init = 1;
|
||||
}
|
||||
}
|
||||
|
||||
up(&xenbus_lock);
|
||||
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(balloon_init_watcher);
|
||||
|
||||
static int balloon_write(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
{
|
||||
@@ -346,7 +427,6 @@ static int balloon_read(char *page, char **start, off_t off,
|
||||
{
|
||||
int len;
|
||||
|
||||
#define K(_p) ((_p)<<(PAGE_SHIFT-10))
|
||||
len = sprintf(
|
||||
page,
|
||||
"Current allocation: %8lu kB\n"
|
||||
@@ -354,13 +434,14 @@ static int balloon_read(char *page, char **start, off_t off,
|
||||
"Low-mem balloon: %8lu kB\n"
|
||||
"High-mem balloon: %8lu kB\n"
|
||||
"Xen hard limit: ",
|
||||
K(current_pages), K(target_pages), K(balloon_low), K(balloon_high));
|
||||
PAGES2KB(current_pages), PAGES2KB(target_pages),
|
||||
PAGES2KB(balloon_low), PAGES2KB(balloon_high));
|
||||
|
||||
if ( hard_limit != ~0UL )
|
||||
len += sprintf(
|
||||
page + len,
|
||||
"%8lu kB (inc. %8lu kB driver headroom)\n",
|
||||
K(hard_limit), K(driver_pages));
|
||||
PAGES2KB(hard_limit), PAGES2KB(driver_pages));
|
||||
else
|
||||
len += sprintf(
|
||||
page + len,
|
||||
@@ -396,9 +477,7 @@ static int __init balloon_init(void)
|
||||
|
||||
balloon_pde->read_proc = balloon_read;
|
||||
balloon_pde->write_proc = balloon_write;
|
||||
|
||||
(void)ctrl_if_register_receiver(CMSG_MEM_REQUEST, balloon_ctrlif_rx, 0);
|
||||
|
||||
|
||||
/* Initialise the balloon with excess memory space. */
|
||||
for ( pfn = xen_start_info.nr_pages; pfn < max_pfn; pfn++ )
|
||||
{
|
||||
@@ -407,6 +486,11 @@ static int __init balloon_init(void)
|
||||
balloon_append(page);
|
||||
}
|
||||
|
||||
xb_watch.callback = watch_target;
|
||||
root_watch.callback = watch_target;
|
||||
|
||||
balloon_init_watcher();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -309,6 +309,9 @@ int do_xenbus_probe(void *unused)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Initialize non-xenbus drivers */
|
||||
balloon_init_watcher();
|
||||
|
||||
down(&xenbus_lock);
|
||||
/* Enumerate devices in xenstore. */
|
||||
xenbus_probe_devices("device");
|
||||
|
||||
@@ -1,391 +0,0 @@
|
||||
/*
|
||||
* linux/kernel/ptrace.c
|
||||
*
|
||||
* (C) Copyright 1999 Linus Torvalds
|
||||
*
|
||||
* Common interfaces for "ptrace()" which we do not want
|
||||
* to continually duplicate across every architecture.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/signal.h>
|
||||
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
/*
|
||||
* ptrace a task: make the debugger its new parent and
|
||||
* move it to the ptrace list.
|
||||
*
|
||||
* Must be called with the tasklist lock write-held.
|
||||
*/
|
||||
void __ptrace_link(task_t *child, task_t *new_parent)
|
||||
{
|
||||
if (!list_empty(&child->ptrace_list))
|
||||
BUG();
|
||||
if (child->parent == new_parent)
|
||||
return;
|
||||
list_add(&child->ptrace_list, &child->parent->ptrace_children);
|
||||
REMOVE_LINKS(child);
|
||||
child->parent = new_parent;
|
||||
SET_LINKS(child);
|
||||
}
|
||||
|
||||
/*
|
||||
* Turn a tracing stop into a normal stop now, since with no tracer there
|
||||
* would be no way to wake it up with SIGCONT or SIGKILL. If there was a
|
||||
* signal sent that would resume the child, but didn't because it was in
|
||||
* TASK_TRACED, resume it now.
|
||||
* Requires that irqs be disabled.
|
||||
*/
|
||||
void ptrace_untrace(task_t *child)
|
||||
{
|
||||
spin_lock(&child->sighand->siglock);
|
||||
if (child->state == TASK_TRACED) {
|
||||
if (child->signal->flags & SIGNAL_STOP_STOPPED) {
|
||||
child->state = TASK_STOPPED;
|
||||
} else {
|
||||
signal_wake_up(child, 1);
|
||||
}
|
||||
}
|
||||
spin_unlock(&child->sighand->siglock);
|
||||
}
|
||||
|
||||
/*
|
||||
* unptrace a task: move it back to its original parent and
|
||||
* remove it from the ptrace list.
|
||||
*
|
||||
* Must be called with the tasklist lock write-held.
|
||||
*/
|
||||
void __ptrace_unlink(task_t *child)
|
||||
{
|
||||
if (!child->ptrace)
|
||||
BUG();
|
||||
child->ptrace = 0;
|
||||
if (!list_empty(&child->ptrace_list)) {
|
||||
list_del_init(&child->ptrace_list);
|
||||
REMOVE_LINKS(child);
|
||||
child->parent = child->real_parent;
|
||||
SET_LINKS(child);
|
||||
}
|
||||
|
||||
if (child->state == TASK_TRACED)
|
||||
ptrace_untrace(child);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that we have indeed attached to the thing..
|
||||
*/
|
||||
int ptrace_check_attach(struct task_struct *child, int kill)
|
||||
{
|
||||
int ret = -ESRCH;
|
||||
|
||||
/*
|
||||
* We take the read lock around doing both checks to close a
|
||||
* possible race where someone else was tracing our child and
|
||||
* detached between these two checks. After this locked check,
|
||||
* we are sure that this is our traced child and that can only
|
||||
* be changed by us so it's not changing right after this.
|
||||
*/
|
||||
read_lock(&tasklist_lock);
|
||||
if ((child->ptrace & PT_PTRACED) && child->parent == current &&
|
||||
(!(child->ptrace & PT_ATTACHED) || child->real_parent != current)
|
||||
&& child->signal != NULL) {
|
||||
ret = 0;
|
||||
spin_lock_irq(&child->sighand->siglock);
|
||||
if (child->state == TASK_STOPPED) {
|
||||
child->state = TASK_TRACED;
|
||||
} else if (child->state != TASK_TRACED && !kill) {
|
||||
ret = -ESRCH;
|
||||
}
|
||||
spin_unlock_irq(&child->sighand->siglock);
|
||||
}
|
||||
read_unlock(&tasklist_lock);
|
||||
|
||||
if (!ret && !kill) {
|
||||
wait_task_inactive(child);
|
||||
}
|
||||
|
||||
/* All systems go.. */
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ptrace_attach(struct task_struct *task)
|
||||
{
|
||||
int retval;
|
||||
task_lock(task);
|
||||
retval = -EPERM;
|
||||
if (task->pid <= 1)
|
||||
goto bad;
|
||||
if (task == current)
|
||||
goto bad;
|
||||
if (!task->mm)
|
||||
goto bad;
|
||||
if(((current->uid != task->euid) ||
|
||||
(current->uid != task->suid) ||
|
||||
(current->uid != task->uid) ||
|
||||
(current->gid != task->egid) ||
|
||||
(current->gid != task->sgid) ||
|
||||
(current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
|
||||
goto bad;
|
||||
smp_rmb();
|
||||
if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
|
||||
goto bad;
|
||||
/* the same process cannot be attached many times */
|
||||
if (task->ptrace & PT_PTRACED)
|
||||
goto bad;
|
||||
retval = security_ptrace(current, task);
|
||||
if (retval)
|
||||
goto bad;
|
||||
|
||||
/* Go */
|
||||
task->ptrace |= PT_PTRACED | ((task->real_parent != current)
|
||||
? PT_ATTACHED : 0);
|
||||
if (capable(CAP_SYS_PTRACE))
|
||||
task->ptrace |= PT_PTRACE_CAP;
|
||||
task_unlock(task);
|
||||
|
||||
write_lock_irq(&tasklist_lock);
|
||||
__ptrace_link(task, current);
|
||||
write_unlock_irq(&tasklist_lock);
|
||||
|
||||
force_sig_specific(SIGSTOP, task);
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
task_unlock(task);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int ptrace_detach(struct task_struct *child, unsigned int data)
|
||||
{
|
||||
if (!valid_signal(data))
|
||||
return -EIO;
|
||||
|
||||
/* Architecture-specific hardware disable .. */
|
||||
ptrace_disable(child);
|
||||
|
||||
/* .. re-parent .. */
|
||||
child->exit_code = data;
|
||||
|
||||
write_lock_irq(&tasklist_lock);
|
||||
__ptrace_unlink(child);
|
||||
/* .. and wake it up. */
|
||||
if (child->exit_state != EXIT_ZOMBIE)
|
||||
wake_up_process(child);
|
||||
write_unlock_irq(&tasklist_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Access another process' address space.
|
||||
* Source/target buffer must be kernel space,
|
||||
* Do not walk the page table directly, use get_user_pages
|
||||
*/
|
||||
|
||||
int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
|
||||
{
|
||||
struct mm_struct *mm;
|
||||
struct vm_area_struct *vma;
|
||||
struct page *page;
|
||||
void *old_buf = buf;
|
||||
|
||||
mm = get_task_mm(tsk);
|
||||
if (!mm)
|
||||
return 0;
|
||||
|
||||
down_read(&mm->mmap_sem);
|
||||
/* ignore errors, just check how much was sucessfully transfered */
|
||||
while (len) {
|
||||
int bytes, ret, offset;
|
||||
void *maddr;
|
||||
|
||||
ret = get_user_pages(tsk, mm, addr, 1,
|
||||
write, 1, &page, &vma);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
|
||||
bytes = len;
|
||||
offset = addr & (PAGE_SIZE-1);
|
||||
if (bytes > PAGE_SIZE-offset)
|
||||
bytes = PAGE_SIZE-offset;
|
||||
|
||||
maddr = kmap(page);
|
||||
if (write) {
|
||||
copy_to_user_page(vma, page, addr,
|
||||
maddr + offset, buf, bytes);
|
||||
set_page_dirty_lock(page);
|
||||
} else {
|
||||
copy_from_user_page(vma, page, addr,
|
||||
buf, maddr + offset, bytes);
|
||||
}
|
||||
kunmap(page);
|
||||
page_cache_release(page);
|
||||
len -= bytes;
|
||||
buf += bytes;
|
||||
addr += bytes;
|
||||
}
|
||||
up_read(&mm->mmap_sem);
|
||||
mmput(mm);
|
||||
|
||||
return buf - old_buf;
|
||||
}
|
||||
EXPORT_SYMBOL(access_process_vm);
|
||||
|
||||
int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len)
|
||||
{
|
||||
int copied = 0;
|
||||
|
||||
while (len > 0) {
|
||||
char buf[128];
|
||||
int this_len, retval;
|
||||
|
||||
this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
|
||||
retval = access_process_vm(tsk, src, buf, this_len, 0);
|
||||
if (!retval) {
|
||||
if (copied)
|
||||
break;
|
||||
return -EIO;
|
||||
}
|
||||
if (copy_to_user(dst, buf, retval))
|
||||
return -EFAULT;
|
||||
copied += retval;
|
||||
src += retval;
|
||||
dst += retval;
|
||||
len -= retval;
|
||||
}
|
||||
return copied;
|
||||
}
|
||||
|
||||
int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len)
|
||||
{
|
||||
int copied = 0;
|
||||
|
||||
while (len > 0) {
|
||||
char buf[128];
|
||||
int this_len, retval;
|
||||
|
||||
this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
|
||||
if (copy_from_user(buf, src, this_len))
|
||||
return -EFAULT;
|
||||
retval = access_process_vm(tsk, dst, buf, this_len, 1);
|
||||
if (!retval) {
|
||||
if (copied)
|
||||
break;
|
||||
return -EIO;
|
||||
}
|
||||
copied += retval;
|
||||
src += retval;
|
||||
dst += retval;
|
||||
len -= retval;
|
||||
}
|
||||
return copied;
|
||||
}
|
||||
|
||||
static int ptrace_setoptions(struct task_struct *child, long data)
|
||||
{
|
||||
child->ptrace &= ~PT_TRACE_MASK;
|
||||
|
||||
if (data & PTRACE_O_TRACESYSGOOD)
|
||||
child->ptrace |= PT_TRACESYSGOOD;
|
||||
|
||||
if (data & PTRACE_O_TRACEFORK)
|
||||
child->ptrace |= PT_TRACE_FORK;
|
||||
|
||||
if (data & PTRACE_O_TRACEVFORK)
|
||||
child->ptrace |= PT_TRACE_VFORK;
|
||||
|
||||
if (data & PTRACE_O_TRACECLONE)
|
||||
child->ptrace |= PT_TRACE_CLONE;
|
||||
|
||||
if (data & PTRACE_O_TRACEEXEC)
|
||||
child->ptrace |= PT_TRACE_EXEC;
|
||||
|
||||
if (data & PTRACE_O_TRACEVFORKDONE)
|
||||
child->ptrace |= PT_TRACE_VFORK_DONE;
|
||||
|
||||
if (data & PTRACE_O_TRACEEXIT)
|
||||
child->ptrace |= PT_TRACE_EXIT;
|
||||
|
||||
return (data & ~PTRACE_O_MASK) ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
static int ptrace_getsiginfo(struct task_struct *child, siginfo_t __user * data)
|
||||
{
|
||||
siginfo_t lastinfo;
|
||||
int error = -ESRCH;
|
||||
|
||||
read_lock(&tasklist_lock);
|
||||
if (likely(child->sighand != NULL)) {
|
||||
error = -EINVAL;
|
||||
spin_lock_irq(&child->sighand->siglock);
|
||||
if (likely(child->last_siginfo != NULL)) {
|
||||
lastinfo = *child->last_siginfo;
|
||||
error = 0;
|
||||
}
|
||||
spin_unlock_irq(&child->sighand->siglock);
|
||||
}
|
||||
read_unlock(&tasklist_lock);
|
||||
if (!error)
|
||||
return copy_siginfo_to_user(data, &lastinfo);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int ptrace_setsiginfo(struct task_struct *child, siginfo_t __user * data)
|
||||
{
|
||||
siginfo_t newinfo;
|
||||
int error = -ESRCH;
|
||||
|
||||
if (copy_from_user(&newinfo, data, sizeof (siginfo_t)))
|
||||
return -EFAULT;
|
||||
|
||||
read_lock(&tasklist_lock);
|
||||
if (likely(child->sighand != NULL)) {
|
||||
error = -EINVAL;
|
||||
spin_lock_irq(&child->sighand->siglock);
|
||||
if (likely(child->last_siginfo != NULL)) {
|
||||
*child->last_siginfo = newinfo;
|
||||
error = 0;
|
||||
}
|
||||
spin_unlock_irq(&child->sighand->siglock);
|
||||
}
|
||||
read_unlock(&tasklist_lock);
|
||||
return error;
|
||||
}
|
||||
|
||||
int ptrace_request(struct task_struct *child, long request,
|
||||
long addr, long data)
|
||||
{
|
||||
int ret = -EIO;
|
||||
|
||||
switch (request) {
|
||||
#ifdef PTRACE_OLDSETOPTIONS
|
||||
case PTRACE_OLDSETOPTIONS:
|
||||
#endif
|
||||
case PTRACE_SETOPTIONS:
|
||||
ret = ptrace_setoptions(child, data);
|
||||
break;
|
||||
case PTRACE_GETEVENTMSG:
|
||||
ret = put_user(child->ptrace_message, (unsigned long __user *) data);
|
||||
break;
|
||||
case PTRACE_GETSIGINFO:
|
||||
ret = ptrace_getsiginfo(child, (siginfo_t __user *) data);
|
||||
break;
|
||||
case PTRACE_SETSIGINFO:
|
||||
ret = ptrace_setsiginfo(child, (siginfo_t __user *) data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1814,12 +1814,12 @@ do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
page_add_anon_rmap(page, vma, addr);
|
||||
}
|
||||
|
||||
set_pte_at(vma, addr, page_table, entry);
|
||||
set_pte_at(mm, addr, page_table, entry);
|
||||
pte_unmap(page_table);
|
||||
|
||||
/* No need to invalidate - it was non-present before */
|
||||
update_mmu_cache(vma, addr, entry);
|
||||
lazy_mmu_prot_update(entry);
|
||||
lazy_mmu_prot_update(entry);
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
out:
|
||||
return VM_FAULT_MINOR;
|
||||
@@ -1928,7 +1928,7 @@ retry:
|
||||
entry = mk_pte(new_page, vma->vm_page_prot);
|
||||
if (write_access)
|
||||
entry = maybe_mkwrite(pte_mkdirty(entry), vma);
|
||||
set_pte_at(vma, address, page_table, entry);
|
||||
set_pte_at(mm, address, page_table, entry);
|
||||
if (anon) {
|
||||
lru_cache_add_active(new_page);
|
||||
page_add_anon_rmap(new_page, vma, address);
|
||||
|
||||
+3
-2
@@ -10,9 +10,10 @@ SUBDIRS += xentrace
|
||||
SUBDIRS += python
|
||||
SUBDIRS += xcs
|
||||
SUBDIRS += xcutils
|
||||
SUBDIRS += pygrub
|
||||
#SUBDIRS += pygrub
|
||||
SUBDIRS += firmware
|
||||
SUBDIRS += policy
|
||||
SUBDIRS += security
|
||||
#SUBDIRS += consoled
|
||||
|
||||
.PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ include $(XEN_ROOT)/Config.mk
|
||||
|
||||
XEN_XC = $(XEN_ROOT)/tools/python/xen/lowlevel/xc
|
||||
XEN_LIBXC = $(XEN_ROOT)/tools/libxc
|
||||
XEN_XCS = $(XEN_ROOT)/tools/xcs
|
||||
XEN_XENSTORE = $(XEN_ROOT)/tools/xenstore
|
||||
|
||||
ifeq ($(XEN_TARGET_ARCH),x86_32)
|
||||
CFLAGS += -m32 -march=i686
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# Makefile for consoled
|
||||
# based on xcs Makefile
|
||||
# Anthony Liguori 2005
|
||||
|
||||
XEN_ROOT=../..
|
||||
include $(XEN_ROOT)/tools/Rules.mk
|
||||
|
||||
CONSOLED_INSTALL_DIR = /usr/sbin
|
||||
XC_CONSOLE_INSTALL_DIR = /usr/libexec/xen
|
||||
|
||||
INSTALL = install
|
||||
INSTALL_PROG = $(INSTALL) -m0755
|
||||
INSTALL_DIR = $(INSTALL) -d -m0755
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -Wall -Werror -g3
|
||||
|
||||
CFLAGS += -I $(XEN_XCS)
|
||||
CFLAGS += -I $(XEN_LIBXC)
|
||||
CFLAGS += -I $(XEN_XENSTORE)
|
||||
|
||||
SRCS :=
|
||||
SRCS += main.c utils.c io.c
|
||||
|
||||
HDRS = $(wildcard *.h)
|
||||
OBJS = $(patsubst %.c,%.o,$(SRCS))
|
||||
BIN = consoled xc_console
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
clean:
|
||||
$(RM) *.a *.so *.o *.rpm $(BIN)
|
||||
|
||||
consoled: $(OBJS)
|
||||
$(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -L$(XEN_XENSTORE) \
|
||||
-lxc -lxenstore
|
||||
|
||||
xc_console: xc_console.o
|
||||
$(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -L$(XEN_XENSTORE) \
|
||||
-lxc -lxenstore
|
||||
|
||||
$(OBJS): $(HDRS)
|
||||
|
||||
install: $(BIN)
|
||||
$(INSTALL_DIR) -p $(DESTDIR)/$(CONSOLED_INSTALL_DIR)
|
||||
$(INSTALL_PROG) consoled $(DESTDIR)/$(CONSOLED_INSTALL_DIR)
|
||||
$(INSTALL_DIR) -p $(DESTDIR)/$(XC_CONSOLE_INSTALL_DIR)
|
||||
$(INSTALL_PROG) xc_console $(DESTDIR)/$(XC_CONSOLE_INSTALL_DIR)
|
||||
@@ -0,0 +1,328 @@
|
||||
/*\
|
||||
* Copyright (C) International Business Machines Corp., 2005
|
||||
* Author(s): Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* Xen Console Daemon
|
||||
*
|
||||
* 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; under version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
\*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "utils.h"
|
||||
#include "io.h"
|
||||
|
||||
#include "xc.h"
|
||||
#include "xs.h"
|
||||
#include "xen/io/domain_controller.h"
|
||||
#include "xcs_proto.h"
|
||||
|
||||
#include <malloc.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/select.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
struct buffer
|
||||
{
|
||||
char *data;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
size_t max_capacity;
|
||||
};
|
||||
|
||||
void buffer_append(struct buffer *buffer, const void *data, size_t size)
|
||||
{
|
||||
if ((buffer->capacity - buffer->size) < size) {
|
||||
buffer->capacity += (size + 1024);
|
||||
buffer->data = realloc(buffer->data, buffer->capacity);
|
||||
if (buffer->data == NULL) {
|
||||
dolog(LOG_ERR, "Memory allocation failed");
|
||||
exit(ENOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(buffer->data + buffer->size, data, size);
|
||||
buffer->size += size;
|
||||
|
||||
if (buffer->max_capacity &&
|
||||
buffer->size > buffer->max_capacity) {
|
||||
memmove(buffer->data + (buffer->size - buffer->max_capacity),
|
||||
buffer->data, buffer->max_capacity);
|
||||
buffer->data = realloc(buffer->data, buffer->max_capacity);
|
||||
buffer->capacity = buffer->max_capacity;
|
||||
}
|
||||
}
|
||||
|
||||
bool buffer_empty(struct buffer *buffer)
|
||||
{
|
||||
return buffer->size == 0;
|
||||
}
|
||||
|
||||
void buffer_advance(struct buffer *buffer, size_t size)
|
||||
{
|
||||
size = MIN(size, buffer->size);
|
||||
memmove(buffer->data, buffer + size, buffer->size - size);
|
||||
buffer->size -= size;
|
||||
}
|
||||
|
||||
struct domain
|
||||
{
|
||||
int domid;
|
||||
int tty_fd;
|
||||
struct buffer buffer;
|
||||
struct domain *next;
|
||||
};
|
||||
|
||||
static struct domain *dom_head;
|
||||
|
||||
bool domain_is_valid(int domid)
|
||||
{
|
||||
bool ret;
|
||||
xc_dominfo_t info;
|
||||
|
||||
ret = (xc_domain_getinfo(xc, domid, 1, &info) == 1 &&
|
||||
info.domid == domid);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int domain_create_tty(int domid)
|
||||
{
|
||||
char path[1024];
|
||||
int master;
|
||||
|
||||
if ((master = getpt()) == -1 ||
|
||||
grantpt(master) == -1 || unlockpt(master) == -1) {
|
||||
dolog(LOG_ERR, "Failed to create tty for domain-%d", domid);
|
||||
master = -1;
|
||||
} else {
|
||||
const char *slave = ptsname(master);
|
||||
struct termios term;
|
||||
|
||||
if (tcgetattr(master, &term) != -1) {
|
||||
cfmakeraw(&term);
|
||||
tcsetattr(master, TCSAFLUSH, &term);
|
||||
}
|
||||
|
||||
xs_mkdir(xs, "/console");
|
||||
snprintf(path, sizeof(path), "/console/%d", domid);
|
||||
xs_mkdir(xs, path);
|
||||
strcat(path, "/tty");
|
||||
|
||||
xs_write(xs, path, slave, strlen(slave), O_CREAT);
|
||||
}
|
||||
|
||||
return master;
|
||||
}
|
||||
|
||||
struct domain *create_domain(int domid)
|
||||
{
|
||||
struct domain *dom;
|
||||
char *data;
|
||||
unsigned int len;
|
||||
char path[1024];
|
||||
|
||||
dom = (struct domain *)malloc(sizeof(struct domain));
|
||||
if (dom == NULL) {
|
||||
dolog(LOG_ERR, "Out of memory %s:%s():L%d",
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
exit(ENOMEM);
|
||||
}
|
||||
|
||||
dom->domid = domid;
|
||||
dom->tty_fd = domain_create_tty(domid);
|
||||
dom->buffer.data = 0;
|
||||
dom->buffer.size = 0;
|
||||
dom->buffer.capacity = 0;
|
||||
dom->buffer.max_capacity = 0;
|
||||
|
||||
snprintf(path, sizeof(path), "/console/%d/limit", domid);
|
||||
data = xs_read(xs, path, &len);
|
||||
if (data) {
|
||||
dom->buffer.max_capacity = strtoul(data, 0, 0);
|
||||
free(data);
|
||||
}
|
||||
|
||||
dolog(LOG_DEBUG, "New domain %d", domid);
|
||||
|
||||
return dom;
|
||||
}
|
||||
|
||||
struct domain *lookup_domain(int domid)
|
||||
{
|
||||
struct domain **pp;
|
||||
|
||||
for (pp = &dom_head; *pp; pp = &(*pp)->next) {
|
||||
struct domain *dom = *pp;
|
||||
|
||||
if (dom->domid == domid) {
|
||||
return dom;
|
||||
} else if (dom->domid > domid) {
|
||||
*pp = create_domain(domid);
|
||||
(*pp)->next = dom;
|
||||
return *pp;
|
||||
}
|
||||
}
|
||||
|
||||
*pp = create_domain(domid);
|
||||
return *pp;
|
||||
}
|
||||
|
||||
void remove_domain(struct domain *dom)
|
||||
{
|
||||
struct domain **pp;
|
||||
|
||||
dolog(LOG_DEBUG, "Removing domain-%d", dom->domid);
|
||||
|
||||
for (pp = &dom_head; *pp; pp = &(*pp)->next) {
|
||||
struct domain *d = *pp;
|
||||
|
||||
if (dom->domid == d->domid) {
|
||||
*pp = d->next;
|
||||
free(d);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handle_tty_read(struct domain *dom)
|
||||
{
|
||||
ssize_t len;
|
||||
xcs_msg_t msg;
|
||||
|
||||
msg.type = XCS_REQUEST;
|
||||
msg.u.control.remote_dom = dom->domid;
|
||||
msg.u.control.msg.type = CMSG_CONSOLE;
|
||||
msg.u.control.msg.subtype = CMSG_CONSOLE_DATA;
|
||||
msg.u.control.msg.id = 1;
|
||||
|
||||
len = read(dom->tty_fd, msg.u.control.msg.msg, 60);
|
||||
if (len < 1) {
|
||||
close(dom->tty_fd);
|
||||
|
||||
if (domain_is_valid(dom->domid)) {
|
||||
dom->tty_fd = domain_create_tty(dom->domid);
|
||||
} else {
|
||||
remove_domain(dom);
|
||||
}
|
||||
} else if (domain_is_valid(dom->domid)) {
|
||||
msg.u.control.msg.length = len;
|
||||
|
||||
if (!write_sync(xcs_data_fd, &msg, sizeof(msg))) {
|
||||
dolog(LOG_ERR, "Write to xcs failed: %m");
|
||||
}
|
||||
} else {
|
||||
close(dom->tty_fd);
|
||||
remove_domain(dom);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_tty_write(struct domain *dom)
|
||||
{
|
||||
ssize_t len;
|
||||
|
||||
len = write(dom->tty_fd, dom->buffer.data, dom->buffer.size);
|
||||
if (len < 1) {
|
||||
close(dom->tty_fd);
|
||||
|
||||
if (domain_is_valid(dom->domid)) {
|
||||
dom->tty_fd = domain_create_tty(dom->domid);
|
||||
} else {
|
||||
remove_domain(dom);
|
||||
}
|
||||
} else {
|
||||
buffer_advance(&dom->buffer, len);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_xcs_msg(int fd)
|
||||
{
|
||||
xcs_msg_t msg;
|
||||
|
||||
if (!read_sync(fd, &msg, sizeof(msg))) {
|
||||
dolog(LOG_ERR, "read from xcs failed! %m");
|
||||
} else if (msg.type == XCS_REQUEST) {
|
||||
struct domain *dom;
|
||||
|
||||
dom = lookup_domain(msg.u.control.remote_dom);
|
||||
buffer_append(&dom->buffer,
|
||||
msg.u.control.msg.msg,
|
||||
msg.u.control.msg.length);
|
||||
}
|
||||
}
|
||||
|
||||
static void enum_domains(void)
|
||||
{
|
||||
int domid = 0;
|
||||
xc_dominfo_t dominfo;
|
||||
|
||||
while (xc_domain_getinfo(xc, domid, 1, &dominfo) == 1) {
|
||||
lookup_domain(dominfo.domid);
|
||||
domid = dominfo.domid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void handle_io(void)
|
||||
{
|
||||
fd_set readfds, writefds;
|
||||
int ret;
|
||||
int max_fd = -1;
|
||||
|
||||
do {
|
||||
struct domain *d;
|
||||
struct timeval tv = { 1, 0 };
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_ZERO(&writefds);
|
||||
|
||||
FD_SET(xcs_data_fd, &readfds);
|
||||
max_fd = MAX(xcs_data_fd, max_fd);
|
||||
|
||||
for (d = dom_head; d; d = d->next) {
|
||||
if (d->tty_fd != -1) {
|
||||
FD_SET(d->tty_fd, &readfds);
|
||||
}
|
||||
|
||||
if (d->tty_fd != -1 && !buffer_empty(&d->buffer)) {
|
||||
FD_SET(d->tty_fd, &writefds);
|
||||
}
|
||||
|
||||
max_fd = MAX(d->tty_fd, max_fd);
|
||||
}
|
||||
|
||||
ret = select(max_fd + 1, &readfds, &writefds, 0, &tv);
|
||||
enum_domains();
|
||||
|
||||
if (FD_ISSET(xcs_data_fd, &readfds)) {
|
||||
handle_xcs_msg(xcs_data_fd);
|
||||
}
|
||||
|
||||
for (d = dom_head; d; d = d->next) {
|
||||
if (FD_ISSET(d->tty_fd, &readfds)) {
|
||||
handle_tty_read(d);
|
||||
}
|
||||
|
||||
if (FD_ISSET(d->tty_fd, &writefds)) {
|
||||
handle_tty_write(d);
|
||||
}
|
||||
}
|
||||
} while (ret > -1);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*\
|
||||
* Copyright (C) International Business Machines Corp., 2005
|
||||
* Author(s): Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* Xen Console Daemon
|
||||
*
|
||||
* 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; under version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
\*/
|
||||
|
||||
#ifndef CONSOLED_IO_H
|
||||
#define CONSOLED_IO_H
|
||||
|
||||
void handle_io(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
/*\
|
||||
* Copyright (C) International Business Machines Corp., 2005
|
||||
* Author(s): Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* Xen Console Daemon
|
||||
*
|
||||
* 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; under version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
\*/
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "xc.h"
|
||||
#include "xen/io/domain_controller.h"
|
||||
#include "xcs_proto.h"
|
||||
|
||||
#include "utils.h"
|
||||
#include "io.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *sopts = "hVvi";
|
||||
struct option lopts[] = {
|
||||
{ "help", 0, 0, 'h' },
|
||||
{ "version", 0, 0, 'V' },
|
||||
{ "verbose", 0, 0, 'v' },
|
||||
{ "interactive", 0, 0, 'i' },
|
||||
{ 0 },
|
||||
};
|
||||
bool is_interactive = false;
|
||||
int ch;
|
||||
int syslog_option = LOG_CONS;
|
||||
int syslog_mask = LOG_WARNING;
|
||||
int opt_ind = 0;
|
||||
|
||||
while ((ch = getopt_long(argc, argv, sopts, lopts, &opt_ind)) != -1) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
//usage(argv[0]);
|
||||
exit(0);
|
||||
case 'V':
|
||||
//version(argv[0]);
|
||||
exit(0);
|
||||
case 'v':
|
||||
syslog_option |= LOG_PERROR;
|
||||
syslog_mask = LOG_DEBUG;
|
||||
break;
|
||||
case 'i':
|
||||
is_interactive = true;
|
||||
break;
|
||||
case '?':
|
||||
fprintf(stderr,
|
||||
"Try `%s --help' for more information\n",
|
||||
argv[0]);
|
||||
exit(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
if (geteuid() != 0) {
|
||||
fprintf(stderr, "%s requires root to run.\n", argv[0]);
|
||||
exit(EPERM);
|
||||
}
|
||||
|
||||
openlog("consoled", syslog_option, LOG_DAEMON);
|
||||
setlogmask(syslog_mask);
|
||||
|
||||
if (!is_interactive) {
|
||||
daemonize("/var/run/consoled.pid");
|
||||
}
|
||||
|
||||
xen_setup();
|
||||
|
||||
handle_io();
|
||||
|
||||
closelog();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
/*\
|
||||
* Copyright (C) International Business Machines Corp., 2005
|
||||
* Author(s): Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* Xen Console Daemon
|
||||
*
|
||||
* 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; under version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
\*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "xc.h"
|
||||
#include "xen/io/domain_controller.h"
|
||||
#include "xcs_proto.h"
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
struct xs_handle *xs;
|
||||
int xc;
|
||||
|
||||
int xcs_ctrl_fd = -1;
|
||||
int xcs_data_fd = -1;
|
||||
|
||||
bool _read_write_sync(int fd, void *data, size_t size, bool do_read)
|
||||
{
|
||||
size_t offset = 0;
|
||||
ssize_t len;
|
||||
|
||||
while (offset < size) {
|
||||
if (do_read) {
|
||||
len = read(fd, data + offset, size - offset);
|
||||
} else {
|
||||
len = write(fd, data + offset, size - offset);
|
||||
}
|
||||
|
||||
if (len < 1) {
|
||||
if (len == -1 && (errno == EAGAIN || errno == EINTR)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
offset += len;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int open_domain_socket(const char *path)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
int sock;
|
||||
size_t addr_len;
|
||||
|
||||
if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy(addr.sun_path, path);
|
||||
addr_len = sizeof(addr.sun_family) + strlen(XCS_SUN_PATH) + 1;
|
||||
|
||||
if (connect(sock, (struct sockaddr *)&addr, addr_len) == -1) {
|
||||
goto out_close_sock;
|
||||
}
|
||||
|
||||
return sock;
|
||||
|
||||
out_close_sock:
|
||||
close(sock);
|
||||
out:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void child_exit(int sig)
|
||||
{
|
||||
while (waitpid(-1, NULL, WNOHANG) > 0);
|
||||
}
|
||||
|
||||
void daemonize(const char *pidfile)
|
||||
{
|
||||
pid_t pid;
|
||||
int fd;
|
||||
int len;
|
||||
int i;
|
||||
char buf[100];
|
||||
|
||||
if (getppid() == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((pid = fork()) > 0) {
|
||||
exit(0);
|
||||
} else if (pid == -1) {
|
||||
err(errno, "fork() failed");
|
||||
}
|
||||
|
||||
setsid();
|
||||
|
||||
/* redirect fd 0,1,2 to /dev/null */
|
||||
if ((fd = open("/dev/null",O_RDWR)) == -1) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i = 0; i <= 2; i++) {
|
||||
close(i);
|
||||
dup2(fd, i);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
umask(027);
|
||||
chdir("/");
|
||||
|
||||
fd = open(pidfile, O_RDWR | O_CREAT);
|
||||
if (fd == -1) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (lockf(fd, F_TLOCK, 0) == -1) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
len = sprintf(buf, "%d\n", getpid());
|
||||
write(fd, buf, len);
|
||||
|
||||
signal(SIGCHLD, child_exit);
|
||||
signal(SIGTSTP, SIG_IGN);
|
||||
signal(SIGTTOU, SIG_IGN);
|
||||
signal(SIGTTIN, SIG_IGN);
|
||||
}
|
||||
|
||||
/* synchronized send/recv strictly for setting up xcs */
|
||||
/* always use asychronize callbacks any other time */
|
||||
static bool xcs_send_recv(int fd, xcs_msg_t *msg)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (!write_sync(fd, msg, sizeof(*msg))) {
|
||||
dolog(LOG_ERR, "Write failed at %s:%s():L%d? Possible bug.",
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!read_sync(fd, msg, sizeof(*msg))) {
|
||||
dolog(LOG_ERR, "Read failed at %s:%s():L%d? Possible bug.",
|
||||
__FILE__, __FUNCTION__, __LINE__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = true;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool xen_setup(void)
|
||||
{
|
||||
int sock;
|
||||
xcs_msg_t msg;
|
||||
|
||||
xs = xs_daemon_open();
|
||||
if (xs == NULL) {
|
||||
dolog(LOG_ERR,
|
||||
"Failed to contact xenstore (%m). Is it running?");
|
||||
goto out;
|
||||
}
|
||||
|
||||
xc = xc_interface_open();
|
||||
if (xc == -1) {
|
||||
dolog(LOG_ERR, "Failed to contact hypervisor (%m)");
|
||||
goto out;
|
||||
}
|
||||
|
||||
sock = open_domain_socket(XCS_SUN_PATH);
|
||||
if (sock == -1) {
|
||||
dolog(LOG_ERR, "Failed to contact xcs (%m). Is it running?");
|
||||
goto out_close_store;
|
||||
}
|
||||
|
||||
xcs_ctrl_fd = sock;
|
||||
|
||||
sock = open_domain_socket(XCS_SUN_PATH);
|
||||
if (sock == -1) {
|
||||
dolog(LOG_ERR, "Failed to contact xcs (%m). Is it running?");
|
||||
goto out_close_ctrl;
|
||||
}
|
||||
|
||||
xcs_data_fd = sock;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.type = XCS_CONNECT_CTRL;
|
||||
if (!xcs_send_recv(xcs_ctrl_fd, &msg) || msg.result != XCS_RSLT_OK) {
|
||||
dolog(LOG_ERR, "xcs control connect failed. Possible bug.");
|
||||
goto out_close_data;
|
||||
}
|
||||
|
||||
msg.type = XCS_CONNECT_DATA;
|
||||
if (!xcs_send_recv(xcs_data_fd, &msg) || msg.result != XCS_RSLT_OK) {
|
||||
dolog(LOG_ERR, "xcs data connect failed. Possible bug.");
|
||||
goto out_close_data;
|
||||
}
|
||||
|
||||
/* Since the vast majority of control messages are console messages
|
||||
it's just easier to ignore other messages that try to bind to
|
||||
a specific type. */
|
||||
msg.type = XCS_MSG_BIND;
|
||||
msg.u.bind.port = PORT_WILDCARD;
|
||||
msg.u.bind.type = TYPE_WILDCARD;
|
||||
if (!xcs_send_recv(xcs_ctrl_fd, &msg) || msg.result != XCS_RSLT_OK) {
|
||||
dolog(LOG_ERR, "xcs vind failed. Possible bug.");
|
||||
goto out_close_data;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
out_close_data:
|
||||
close(xcs_ctrl_fd);
|
||||
xcs_data_fd = -1;
|
||||
out_close_ctrl:
|
||||
close(xcs_ctrl_fd);
|
||||
xcs_ctrl_fd = -1;
|
||||
out_close_store:
|
||||
xs_daemon_close(xs);
|
||||
out:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*\
|
||||
* Copyright (C) International Business Machines Corp., 2005
|
||||
* Author(s): Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* Xen Console Daemon
|
||||
*
|
||||
* 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; under version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
\*/
|
||||
|
||||
#ifndef CONSOLED_UTILS_H
|
||||
#define CONSOLED_UTILS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <syslog.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "xs.h"
|
||||
|
||||
void daemonize(const char *pidfile);
|
||||
bool xen_setup(void);
|
||||
#define read_sync(fd, buffer, size) _read_write_sync(fd, buffer, size, true)
|
||||
#define write_sync(fd, buffer, size) _read_write_sync(fd, buffer, size, false)
|
||||
bool _read_write_sync(int fd, void *data, size_t size, bool do_read);
|
||||
|
||||
extern int xcs_ctrl_fd;
|
||||
extern int xcs_data_fd;
|
||||
extern struct xs_handle *xs;
|
||||
extern int xc;
|
||||
|
||||
#if 1
|
||||
#define dolog(val, fmt, ...) syslog(val, fmt, ## __VA_ARGS__)
|
||||
#else
|
||||
#define dolog(val, fmt, ...) fprintf(stderr, fmt "\n", ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,236 @@
|
||||
/*\
|
||||
* Copyright (C) International Business Machines Corp., 2005
|
||||
* Author(s): Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* Xen Console Daemon
|
||||
*
|
||||
* 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; under version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
\*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <termios.h>
|
||||
#include <signal.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/select.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <pty.h>
|
||||
|
||||
#include "xc.h"
|
||||
#include "xs.h"
|
||||
|
||||
#define ESCAPE_CHARACTER 0x1d
|
||||
|
||||
static volatile sig_atomic_t received_signal = 0;
|
||||
|
||||
static void sighandler(int signum)
|
||||
{
|
||||
received_signal = 1;
|
||||
}
|
||||
|
||||
static bool write_sync(int fd, const void *data, size_t size)
|
||||
{
|
||||
size_t offset = 0;
|
||||
ssize_t len;
|
||||
|
||||
while (offset < size) {
|
||||
len = write(fd, data + offset, size - offset);
|
||||
if (len < 1) {
|
||||
return false;
|
||||
}
|
||||
offset += len;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void usage(const char *program) {
|
||||
printf("Usage: %s [OPTION] DOMID\n"
|
||||
"Attaches to a virtual domain console\n"
|
||||
"\n"
|
||||
" -h, --help display this help and exit\n"
|
||||
, program);
|
||||
}
|
||||
|
||||
/* don't worry too much if setting terminal attributes fail */
|
||||
static void init_term(int fd, struct termios *old)
|
||||
{
|
||||
struct termios new_term;
|
||||
|
||||
if (tcgetattr(fd, old) == -1) {
|
||||
perror("tcgetattr() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
new_term = *old;
|
||||
cfmakeraw(&new_term);
|
||||
|
||||
if (tcsetattr(fd, TCSAFLUSH, &new_term) == -1) {
|
||||
perror("tcsetattr() failed");
|
||||
}
|
||||
}
|
||||
|
||||
static void restore_term(int fd, struct termios *old)
|
||||
{
|
||||
if (tcsetattr(fd, TCSAFLUSH, old) == -1) {
|
||||
perror("tcsetattr() failed");
|
||||
}
|
||||
}
|
||||
|
||||
static int console_loop(int xc_handle, domid_t domid, int fd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
do {
|
||||
fd_set fds;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(STDIN_FILENO, &fds);
|
||||
FD_SET(fd, &fds);
|
||||
|
||||
ret = select(fd + 1, &fds, NULL, NULL, NULL);
|
||||
if (ret == -1) {
|
||||
if (errno == EINTR || errno == EAGAIN) {
|
||||
continue;
|
||||
}
|
||||
perror("select() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (FD_ISSET(STDIN_FILENO, &fds)) {
|
||||
ssize_t len;
|
||||
char msg[60];
|
||||
|
||||
len = read(STDIN_FILENO, msg, sizeof(msg));
|
||||
if (len == 1 && msg[0] == ESCAPE_CHARACTER) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (len == 0 && len == -1) {
|
||||
if (len == -1 &&
|
||||
(errno == EINTR || errno == EAGAIN)) {
|
||||
continue;
|
||||
}
|
||||
perror("select() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!write_sync(fd, msg, len)) {
|
||||
perror("write() failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (FD_ISSET(fd, &fds)) {
|
||||
ssize_t len;
|
||||
char msg[512];
|
||||
|
||||
len = read(fd, msg, sizeof(msg));
|
||||
if (len == 0 || len == -1) {
|
||||
if (len == -1 &&
|
||||
(errno == EINTR || errno == EAGAIN)) {
|
||||
continue;
|
||||
}
|
||||
perror("select() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!write_sync(STDOUT_FILENO, msg, len)) {
|
||||
perror("write() failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} while (received_signal == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct termios attr;
|
||||
int domid;
|
||||
int xc_handle;
|
||||
char *sopt = "hf:pc";
|
||||
int ch;
|
||||
int opt_ind=0;
|
||||
struct option lopt[] = {
|
||||
{ "help", 0, 0, 'h' },
|
||||
{ "file", 1, 0, 'f' },
|
||||
{ "pty", 0, 0, 'p' },
|
||||
{ "ctty", 0, 0, 'c' },
|
||||
{ 0 },
|
||||
|
||||
};
|
||||
char *str_pty;
|
||||
char path[1024];
|
||||
int spty;
|
||||
unsigned int len = 0;
|
||||
struct xs_handle *xs;
|
||||
|
||||
while((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
|
||||
switch(ch) {
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((argc - optind) != 1) {
|
||||
fprintf(stderr, "Invalid number of arguments\n");
|
||||
fprintf(stderr, "Try `%s --help' for more information.\n",
|
||||
argv[0]);
|
||||
exit(EINVAL);
|
||||
}
|
||||
|
||||
domid = atoi(argv[optind]);
|
||||
|
||||
xs = xs_daemon_open();
|
||||
if (xs == NULL) {
|
||||
err(errno, "Could not contact XenStore");
|
||||
}
|
||||
|
||||
xc_handle = xc_interface_open();
|
||||
if (xc_handle == -1) {
|
||||
err(errno, "xc_interface_open()");
|
||||
}
|
||||
|
||||
signal(SIGTERM, sighandler);
|
||||
|
||||
snprintf(path, sizeof(path), "/console/%d/tty", domid);
|
||||
str_pty = xs_read(xs, path, &len);
|
||||
if (str_pty == NULL) {
|
||||
err(errno, "Could not read tty from store");
|
||||
}
|
||||
spty = open(str_pty, O_RDWR | O_NOCTTY);
|
||||
if (spty == -1) {
|
||||
err(errno, "Could not open tty `%s'", str_pty);
|
||||
}
|
||||
free(str_pty);
|
||||
|
||||
init_term(STDIN_FILENO, &attr);
|
||||
console_loop(xc_handle, domid, spty);
|
||||
restore_term(STDIN_FILENO, &attr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#include "xc_private.h"
|
||||
|
||||
int xc_linux_save(int xc_handle, int io_fd, u32 dom)
|
||||
{
|
||||
PERROR("xc_linux_save not implemented\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns)
|
||||
{
|
||||
PERROR("xc_linux_restore not implemented\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int xc_vmx_build(int xc_handle,
|
||||
u32 domid,
|
||||
int memsize,
|
||||
const char *image_name,
|
||||
struct mem_map *mem_mapp,
|
||||
const char *ramdisk_name,
|
||||
const char *cmdline,
|
||||
unsigned int control_evtchn,
|
||||
unsigned long flags)
|
||||
{
|
||||
PERROR("xc_vmx_build not implemented\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
xc_plan9_build(int xc_handle,
|
||||
u32 domid,
|
||||
const char *image_name,
|
||||
const char *cmdline,
|
||||
unsigned int control_evtchn, unsigned long flags)
|
||||
{
|
||||
PERROR("xc_plan9_build not implemented\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
XEN_ROOT = ../../..
|
||||
include $(XEN_ROOT)/tools/Rules.mk
|
||||
|
||||
CFLAGS += -static
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Werror
|
||||
CFLAGS += -O3
|
||||
CFLAGS += -fno-strict-aliasing
|
||||
CFLAGS += -I.
|
||||
|
||||
all: build
|
||||
|
||||
build: mk-symlinks
|
||||
$(MAKE) xml_to_bin
|
||||
|
||||
default: all
|
||||
|
||||
install: all
|
||||
|
||||
xml_to_bin : make_include XmlToBin.java XmlToBinInterface.java SsidsEntry.java SecurityLabel.java myHandler.java
|
||||
javac XmlToBin.java
|
||||
|
||||
make_include : c2j_include
|
||||
./c2j_include
|
||||
|
||||
c2j_include: c2j_include.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -rf *.class xen c2j_include policy_version.java *.bin
|
||||
|
||||
|
||||
LINUX_ROOT := $(XEN_ROOT)/linux-2.6-xen-sparse
|
||||
mk-symlinks:
|
||||
[ -e xen/linux ] || mkdir -p xen/linux
|
||||
[ -e xen/io ] || mkdir -p xen/io
|
||||
( cd xen >/dev/null ; \
|
||||
ln -sf ../$(XEN_ROOT)/xen/include/public/*.h . )
|
||||
( cd xen/io >/dev/null ; \
|
||||
ln -sf ../../$(XEN_ROOT)/xen/include/public/io/*.h . )
|
||||
( cd xen/linux >/dev/null ; \
|
||||
ln -sf ../../$(LINUX_ROOT)/include/asm-xen/linux-public/*.h . )
|
||||
@@ -5,6 +5,9 @@
|
||||
*
|
||||
* Author: Ray Valdez
|
||||
*
|
||||
* Contributors:
|
||||
* Reiner Sailer - adjust type-lengths
|
||||
*
|
||||
* 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
|
||||
@@ -490,175 +493,139 @@ public class XmlToBin
|
||||
|
||||
|
||||
try {
|
||||
/* Write magic */
|
||||
writeIntToStream(binBuffer,ACM_MAGIC,index);
|
||||
index = u32Size;
|
||||
index = 0;
|
||||
/* fill in General Policy Version */
|
||||
writeIntToStream(binBuffer, ACM_POLICY_VERSION, index);
|
||||
index += u32Size;
|
||||
|
||||
/* Write policy version */
|
||||
writeIntToStream(binBuffer,POLICY_INTERFACE_VERSION,index);
|
||||
index = index + u32Size;
|
||||
/* Write magic */
|
||||
writeIntToStream(binBuffer, ACM_MAGIC, index);
|
||||
index += u32Size;
|
||||
|
||||
/* write len */
|
||||
writeIntToStream(binBuffer,binBuffer.length,index);
|
||||
index = index + u32Size;
|
||||
/* write len */
|
||||
writeIntToStream(binBuffer, binBuffer.length, index);
|
||||
index += u32Size;
|
||||
|
||||
} catch (IOException ee) {
|
||||
System.out.println(" GBPB:: got exception : " + ee);
|
||||
return null;
|
||||
System.out.println(" GBPB:: got exception : " + ee);
|
||||
return null;
|
||||
}
|
||||
|
||||
int offset, address;
|
||||
address = index;
|
||||
|
||||
if (null != partMap)
|
||||
offset = binaryBufferHeaderSz + resourceOffsetSz;
|
||||
offset = binaryBufferHeaderSz + resourceOffsetSz;
|
||||
else
|
||||
offset = binaryBufferHeaderSz;
|
||||
offset = binaryBufferHeaderSz;
|
||||
|
||||
try {
|
||||
int skip = 0;
|
||||
|
||||
if (null == chwPolicy || null == stePolicy)
|
||||
{
|
||||
writeShortToStream(binBuffer,ACM_NULL_POLICY,index);
|
||||
index = index + u16Size;
|
||||
|
||||
writeShortToStream(binBuffer,(short) 0,index);
|
||||
index = index + u16Size;
|
||||
|
||||
writeShortToStream(binBuffer,ACM_NULL_POLICY,index);
|
||||
index = index + u16Size;
|
||||
|
||||
writeShortToStream(binBuffer,(short) 0,index);
|
||||
index = index + u16Size;
|
||||
|
||||
}
|
||||
index = address;
|
||||
if (null != chwPolicy)
|
||||
{
|
||||
/* init with NULL policy setting */
|
||||
writeIntToStream(binBuffer, ACM_NULL_POLICY, index);
|
||||
writeIntToStream(binBuffer, 0, index + u32Size);
|
||||
writeIntToStream(binBuffer, ACM_NULL_POLICY, index + 2*u32Size);
|
||||
writeIntToStream(binBuffer, 0, index + 3*u32Size);
|
||||
|
||||
/* Write policy name */
|
||||
writeShortToStream(binBuffer,ACM_CHINESE_WALL_POLICY,index);
|
||||
index = index + u16Size;
|
||||
|
||||
/* Write offset */
|
||||
writeShortToStream(binBuffer,(short) offset,index);
|
||||
index = index + u16Size;
|
||||
|
||||
/* Write payload. No need increment index */
|
||||
address = offset;
|
||||
System.arraycopy(chwPolicy, 0, binBuffer,address, chwPolicy.length);
|
||||
address = address + chwPolicy.length;
|
||||
|
||||
if (null != stePolicy)
|
||||
{
|
||||
/* Write policy name */
|
||||
writeShortToStream(binBuffer,ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,index);
|
||||
index = index + u16Size;
|
||||
|
||||
/* Write offset */
|
||||
writeShortToStream(binBuffer,(short) address,index);
|
||||
index = index + u16Size;
|
||||
|
||||
/* Copy array */
|
||||
System.arraycopy(stePolicy, 0, binBuffer,address, stePolicy.length);
|
||||
/* Update address */
|
||||
address = address + stePolicy.length;
|
||||
} else {
|
||||
/* Skip writing policy name and offset */
|
||||
index = index + 2 * u16Size;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (null != stePolicy)
|
||||
{
|
||||
/* Write policy name */
|
||||
writeShortToStream(binBuffer,ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,index);
|
||||
index = index + u16Size;
|
||||
|
||||
/* Write offset */
|
||||
address = offset;
|
||||
writeShortToStream(binBuffer, (short) offset,index);
|
||||
index = index + u16Size;
|
||||
|
||||
/* Copy array */
|
||||
System.arraycopy(stePolicy, 0, binBuffer,address, stePolicy.length);
|
||||
/* Update address */
|
||||
address = address + stePolicy.length;
|
||||
|
||||
/* Increment index, since there is no secondary */
|
||||
index = index + secondaryPolicyCodeSz + secondaryBufferOffsetSz;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
int size;
|
||||
/* Assumes that you will always have a partition defined in policy */
|
||||
if ( 0 < partMap.length)
|
||||
{
|
||||
writeShortToStream(binBuffer, (short) address,index);
|
||||
index = address;
|
||||
|
||||
/* Compute num of VMs */
|
||||
size = partMap.length / (3 * u16Size);
|
||||
|
||||
writeShortToStream(binBuffer, (short)size,index);
|
||||
index = index + u16Size;
|
||||
|
||||
/* part, vlan and slot: each one consists of two entries */
|
||||
offset = 3 * (2 * u16Size);
|
||||
writeShortToStream(binBuffer, (short) offset,index);
|
||||
|
||||
/* Write partition array at offset */
|
||||
System.arraycopy(partMap, 0, binBuffer,(offset + address), partMap.length);
|
||||
index = index + u16Size;
|
||||
offset = offset + partMap.length;
|
||||
}
|
||||
|
||||
if ( 0 < vlanMap.length)
|
||||
{
|
||||
size = vlanMap.length / (2 * u16Size);
|
||||
writeShortToStream(binBuffer, (short) size,index);
|
||||
index = index + u16Size;
|
||||
|
||||
writeShortToStream(binBuffer, (short) offset,index);
|
||||
index = index + u16Size;
|
||||
System.arraycopy(vlanMap, 0, binBuffer,(offset + address), vlanMap.length);
|
||||
} else {
|
||||
/* Write vlan max */
|
||||
writeShortToStream(binBuffer, (short) 0,index);
|
||||
index = index + u16Size;
|
||||
|
||||
/* Write vlan offset */
|
||||
writeShortToStream(binBuffer, (short) 0,index);
|
||||
index = index + u16Size;
|
||||
if (null != chwPolicy) {
|
||||
|
||||
}
|
||||
/* Write policy name */
|
||||
writeIntToStream(binBuffer, ACM_CHINESE_WALL_POLICY, index);
|
||||
index += u32Size;
|
||||
|
||||
offset = offset + vlanMap.length;
|
||||
if ( 0 < slotMap.length)
|
||||
{
|
||||
size = slotMap.length / (3 * u16Size);
|
||||
writeShortToStream(binBuffer, (short) size,index);
|
||||
index = index + u16Size;
|
||||
/* Write offset */
|
||||
writeIntToStream(binBuffer, offset, index);
|
||||
index += u32Size;
|
||||
|
||||
writeShortToStream(binBuffer, (short) offset,index);
|
||||
index = index + u16Size;
|
||||
System.arraycopy(slotMap, 0, binBuffer,(offset + address), slotMap.length);
|
||||
}
|
||||
/* Write payload. No need increment index */
|
||||
address = offset;
|
||||
System.arraycopy(chwPolicy, 0, binBuffer,address, chwPolicy.length);
|
||||
address = address + chwPolicy.length;
|
||||
} else
|
||||
skip += 2*u32Size;
|
||||
|
||||
} catch (IOException ee)
|
||||
{
|
||||
System.out.println(" GBPB:: got exception : " + ee);
|
||||
return null;
|
||||
}
|
||||
if (null != stePolicy)
|
||||
{
|
||||
/* Write policy name */
|
||||
writeIntToStream(binBuffer, ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, index);
|
||||
index += u32Size;
|
||||
|
||||
printDebug(" GBP:: Binary Policy ==> length " + binBuffer.length);
|
||||
if (debug)
|
||||
printHex(binBuffer,binBuffer.length);
|
||||
/* Write offset */
|
||||
writeIntToStream(binBuffer, address, index);
|
||||
index += u32Size;
|
||||
|
||||
return binBuffer;
|
||||
/* Copy array */
|
||||
System.arraycopy(stePolicy, 0, binBuffer,address, stePolicy.length);
|
||||
/* Update address */
|
||||
address = address + stePolicy.length;
|
||||
} else
|
||||
skip += 2*u32Size;
|
||||
|
||||
/* Skip writing policy name and offset for each null policy*/
|
||||
index += skip;
|
||||
|
||||
int size;
|
||||
/* Assumes that you will always have a partition defined in policy */
|
||||
if ( 0 < partMap.length) {
|
||||
writeIntToStream(binBuffer, address, index);
|
||||
index = address;
|
||||
|
||||
/* Compute num of VMs */
|
||||
size = partMap.length / (3 * u16Size);
|
||||
|
||||
writeShortToStream(binBuffer, (short)size,index);
|
||||
index = index + u16Size;
|
||||
|
||||
/* part, vlan and slot: each one consists of two entries */
|
||||
offset = 3 * (2 * u16Size);
|
||||
writeShortToStream(binBuffer, (short) offset,index);
|
||||
|
||||
/* Write partition array at offset */
|
||||
System.arraycopy(partMap, 0, binBuffer,(offset + address), partMap.length);
|
||||
index = index + u16Size;
|
||||
offset = offset + partMap.length;
|
||||
}
|
||||
|
||||
if ( 0 < vlanMap.length) {
|
||||
size = vlanMap.length / (2 * u16Size);
|
||||
writeShortToStream(binBuffer, (short) size,index);
|
||||
index = index + u16Size;
|
||||
|
||||
writeShortToStream(binBuffer, (short) offset,index);
|
||||
index = index + u16Size;
|
||||
System.arraycopy(vlanMap, 0, binBuffer,(offset + address), vlanMap.length);
|
||||
} else {
|
||||
/* Write vlan max */
|
||||
writeShortToStream(binBuffer, (short) 0,index);
|
||||
index = index + u16Size;
|
||||
|
||||
/* Write vlan offset */
|
||||
writeShortToStream(binBuffer, (short) 0,index);
|
||||
index = index + u16Size;
|
||||
}
|
||||
|
||||
offset = offset + vlanMap.length;
|
||||
if ( 0 < slotMap.length) {
|
||||
size = slotMap.length / (3 * u16Size);
|
||||
writeShortToStream(binBuffer, (short) size,index);
|
||||
index = index + u16Size;
|
||||
|
||||
writeShortToStream(binBuffer, (short) offset,index);
|
||||
index = index + u16Size;
|
||||
System.arraycopy(slotMap, 0, binBuffer,(offset + address), slotMap.length);
|
||||
}
|
||||
} catch (IOException ee) {
|
||||
System.out.println(" GBPB:: got exception : " + ee);
|
||||
return null;
|
||||
}
|
||||
|
||||
printDebug(" GBP:: Binary Policy ==> length " + binBuffer.length);
|
||||
if (debug)
|
||||
printHex(binBuffer,binBuffer.length);
|
||||
|
||||
return binBuffer;
|
||||
}
|
||||
|
||||
public byte[] generateChwBuffer(Vector Ssids, Vector ConflictSsids, Vector ColorTypes)
|
||||
@@ -668,28 +635,20 @@ public class XmlToBin
|
||||
int position = 0;
|
||||
|
||||
/* Get number of rTypes */
|
||||
short maxTypes = (short) ColorTypes.size();
|
||||
int maxTypes = ColorTypes.size();
|
||||
|
||||
/* Get number of SSids entry */
|
||||
short maxSsids = (short) Ssids.size();
|
||||
int maxSsids = Ssids.size();
|
||||
|
||||
/* Get number of conflict sets */
|
||||
short maxConflict = (short) ConflictSsids.size();
|
||||
int maxConflict = ConflictSsids.size();
|
||||
|
||||
|
||||
if (maxTypes * maxSsids == 0)
|
||||
return null;
|
||||
/*
|
||||
data structure acm_chwall_policy_buffer_t;
|
||||
|
||||
uint16 policy_code;
|
||||
uint16 chwall_max_types;
|
||||
uint16 chwall_max_ssidrefs;
|
||||
uint16 chwall_max_conflictsets;
|
||||
uint16 chwall_ssid_offset;
|
||||
uint16 chwall_conflict_sets_offset;
|
||||
uint16 chwall_running_types_offset;
|
||||
uint16 chwall_conflict_aggregate_offset;
|
||||
data structure acm_chwall_policy_buffer
|
||||
se XmlToBinInterface.java
|
||||
*/
|
||||
int totalBytes = chwHeaderSize + u16Size *(maxTypes * (maxSsids + maxConflict));
|
||||
|
||||
@@ -699,34 +658,38 @@ public class XmlToBin
|
||||
printDebug(" gCB:: chwall totalbytes : "+totalBytes);
|
||||
|
||||
try {
|
||||
index = 0;
|
||||
writeShortToStream(chwBuffer,ACM_CHINESE_WALL_POLICY,index);
|
||||
index = u16Size;
|
||||
index = 0;
|
||||
/* fill in General Policy Version */
|
||||
writeIntToStream(chwBuffer, ACM_CHWALL_VERSION, index);
|
||||
index += u32Size;
|
||||
|
||||
writeShortToStream(chwBuffer,maxTypes,index);
|
||||
index = index + u16Size;
|
||||
writeIntToStream(chwBuffer, ACM_CHINESE_WALL_POLICY, index);
|
||||
index += u32Size;
|
||||
|
||||
writeShortToStream(chwBuffer,maxSsids,index);
|
||||
index = index + u16Size;
|
||||
writeIntToStream(chwBuffer, maxTypes, index);
|
||||
index += u32Size;
|
||||
|
||||
writeShortToStream(chwBuffer,maxConflict,index);
|
||||
index = index + u16Size;
|
||||
writeIntToStream(chwBuffer, maxSsids, index);
|
||||
index += u32Size;
|
||||
|
||||
/* Write chwall_ssid_offset */
|
||||
writeShortToStream(chwBuffer,chwHeaderSize,index);
|
||||
index = index + u16Size;
|
||||
writeIntToStream(chwBuffer, maxConflict, index);
|
||||
index += u32Size;
|
||||
|
||||
/* Write chwall_conflict_sets_offset */
|
||||
writeShortToStream(chwBuffer,(short) address,index);
|
||||
index = index + u16Size;
|
||||
/* Write chwall_ssid_offset */
|
||||
writeIntToStream(chwBuffer, chwHeaderSize, index);
|
||||
index += u32Size;
|
||||
|
||||
/* Write chwall_running_types_offset */
|
||||
writeShortToStream(chwBuffer,(short) 0,index);
|
||||
index = index + u16Size;
|
||||
/* Write chwall_conflict_sets_offset */
|
||||
writeIntToStream(chwBuffer, address, index);
|
||||
index += u32Size;
|
||||
|
||||
/* Write chwall_conflict_aggregate_offset */
|
||||
writeShortToStream(chwBuffer,(short) 0,index);
|
||||
index = index + u16Size;
|
||||
/* Write chwall_running_types_offset */
|
||||
writeIntToStream(chwBuffer, 0, index);
|
||||
index += u32Size;
|
||||
|
||||
/* Write chwall_conflict_aggregate_offset */
|
||||
writeIntToStream(chwBuffer, 0, index);
|
||||
index += u32Size;
|
||||
|
||||
} catch (IOException ee) {
|
||||
System.out.println(" gCB:: got exception : " + ee);
|
||||
@@ -737,7 +700,6 @@ public class XmlToBin
|
||||
/* Create the SSids entry */
|
||||
for (int i = 0; i < maxSsids; i++)
|
||||
{
|
||||
|
||||
SecurityLabel ssidEntry = (SecurityLabel) Ssids.elementAt(i);
|
||||
/* Get chwall types */
|
||||
ssidEntry.chwSsidPosition = i;
|
||||
@@ -821,22 +783,16 @@ public class XmlToBin
|
||||
int position = 0;
|
||||
|
||||
/* Get number of colorTypes */
|
||||
short numColorTypes = (short) ColorTypes.size();
|
||||
int numColorTypes = ColorTypes.size();
|
||||
|
||||
/* Get number of SSids entry */
|
||||
short numSsids = (short) Ssids.size();
|
||||
int numSsids = Ssids.size();
|
||||
|
||||
if (numColorTypes * numSsids == 0)
|
||||
return null;
|
||||
|
||||
/* data structure: acm_ste_policy_buffer_t
|
||||
*
|
||||
* policy code (uint16) >
|
||||
* max_types (uint16) >
|
||||
* max_ssidrefs (uint16) > steHeaderSize
|
||||
* ssid_offset (uint16) >
|
||||
* DATA (colorTypes(size) * Ssids(size) *unit16)
|
||||
*
|
||||
/* data structure: acm_ste_policy_buffer
|
||||
* see XmlToBinInterface.java
|
||||
* total bytes: steHeaderSize * 2B + colorTypes(size) * Ssids(size)
|
||||
*
|
||||
*/
|
||||
@@ -844,18 +800,22 @@ public class XmlToBin
|
||||
|
||||
try {
|
||||
|
||||
index = 0;
|
||||
writeShortToStream(steBuffer,ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,index);
|
||||
index = u16Size;
|
||||
index = 0;
|
||||
writeIntToStream(steBuffer, ACM_STE_VERSION, index);
|
||||
index += u32Size;
|
||||
|
||||
writeShortToStream(steBuffer,numColorTypes,index);
|
||||
index = index + u16Size;
|
||||
writeIntToStream(steBuffer, ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, index);
|
||||
index += u32Size;
|
||||
|
||||
writeShortToStream(steBuffer,numSsids,index);
|
||||
index = index + u16Size;
|
||||
writeIntToStream(steBuffer, numColorTypes, index);
|
||||
index += u32Size;
|
||||
|
||||
writeIntToStream(steBuffer, numSsids, index);
|
||||
index += u32Size;
|
||||
|
||||
writeIntToStream(steBuffer, steHeaderSize, index);
|
||||
index += u32Size;
|
||||
|
||||
writeShortToStream(steBuffer,(short)steHeaderSize,index);
|
||||
index = index + u16Size;
|
||||
|
||||
} catch (IOException ee) {
|
||||
System.out.println(" gSB:: got exception : " + ee);
|
||||
@@ -1469,6 +1429,17 @@ public class XmlToBin
|
||||
|
||||
XmlToBin genObj = new XmlToBin();
|
||||
|
||||
policy_version active_policy = new policy_version();
|
||||
|
||||
if ((active_policy.ACM_POLICY_VERSION != ACM_POLICY_VERSION) ||
|
||||
(active_policy.ACM_CHWALL_VERSION != ACM_CHWALL_VERSION) ||
|
||||
(active_policy.ACM_STE_VERSION != ACM_STE_VERSION)) {
|
||||
System.out.println("ACM policy versions differ.");
|
||||
System.out.println("Please verify that data structures are correct");
|
||||
System.out.println("and then adjust the version numbers in XmlToBinInterface.java.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0 ; i < args.length ; i++) {
|
||||
|
||||
|
||||
@@ -19,37 +19,37 @@
|
||||
*
|
||||
* policy binary structures
|
||||
*
|
||||
* typedef struct {
|
||||
* u32 magic;
|
||||
* struct acm_policy_buffer {
|
||||
* u32 policy_version; * ACM_POLICY_VERSION *
|
||||
* u32 magic;
|
||||
* u32 len;
|
||||
* u32 primary_policy_code;
|
||||
* u32 primary_buffer_offset;
|
||||
* u32 secondary_policy_code;
|
||||
* u32 secondary_buffer_offset;
|
||||
* +u32 resource offset (not used yet in Xen)
|
||||
* };
|
||||
*
|
||||
* u32 policyversion;
|
||||
* u32 len;
|
||||
*
|
||||
* u16 primary_policy_code;
|
||||
* u16 primary_buffer_offset;
|
||||
* u16 secondary_policy_code;
|
||||
* u16 secondary_buffer_offset;
|
||||
* u16 resource_offset;
|
||||
* struct acm_ste_policy_buffer {
|
||||
* u32 policy_version; * ACM_STE_VERSION *
|
||||
* u32 policy_code;
|
||||
* u32 ste_max_types;
|
||||
* u32 ste_max_ssidrefs;
|
||||
* u32 ste_ssid_offset;
|
||||
* };
|
||||
*
|
||||
* } acm_policy_buffer_t;
|
||||
*
|
||||
* typedef struct {
|
||||
* u16 policy_code;
|
||||
* u16 ste_max_types;
|
||||
* u16 ste_max_ssidrefs;
|
||||
* u16 ste_ssid_offset;
|
||||
* } acm_ste_policy_buffer_t;
|
||||
*
|
||||
* typedef struct {
|
||||
* uint16 policy_code;
|
||||
* uint16 chwall_max_types;
|
||||
* uint16 chwall_max_ssidrefs;
|
||||
* uint16 chwall_max_conflictsets;
|
||||
* uint16 chwall_ssid_offset;
|
||||
* uint16 chwall_conflict_sets_offset;
|
||||
* uint16 chwall_running_types_offset;
|
||||
* uint16 chwall_conflict_aggregate_offset;
|
||||
* } acm_chwall_policy_buffer_t;
|
||||
* struct acm_chwall_policy_buffer {
|
||||
* u32 policy_version; * ACM_CHWALL_VERSION *
|
||||
* u32 policy_code;
|
||||
* u32 chwall_max_types;
|
||||
* u32 chwall_max_ssidrefs;
|
||||
* u32 chwall_max_conflictsets;
|
||||
* u32 chwall_ssid_offset;
|
||||
* u32 chwall_conflict_sets_offset;
|
||||
* u32 chwall_running_types_offset;
|
||||
* u32 chwall_conflict_aggregate_offset;
|
||||
* };
|
||||
*
|
||||
* typedef struct {
|
||||
* u16 partition_max;
|
||||
@@ -100,16 +100,17 @@ public interface XmlToBinInterface
|
||||
final int u16Size = 2;
|
||||
|
||||
/* num of bytes for acm_ste_policy_buffer_t */
|
||||
final short steHeaderSize = (4 * u16Size);
|
||||
final int steHeaderSize = (5 * u32Size);
|
||||
|
||||
/* byte for acm_chinese_wall_policy_buffer_t */
|
||||
final short chwHeaderSize = (8 * u16Size);
|
||||
final int chwHeaderSize = (9 * u32Size);
|
||||
|
||||
final short primaryPolicyCodeSize = u16Size;
|
||||
final short primaryBufferOffsetSize = u16Size ;
|
||||
final int primaryPolicyCodeSize = u32Size;
|
||||
final int primaryBufferOffsetSize = u32Size ;
|
||||
|
||||
final int secondaryPolicyCodeSz = u16Size;
|
||||
final int secondaryBufferOffsetSz = u16Size;
|
||||
final short resourceOffsetSz = u16Size;
|
||||
final int secondaryPolicyCodeSz = u32Size;
|
||||
final int secondaryBufferOffsetSz = u32Size;
|
||||
final int resourceOffsetSz = u32Size;
|
||||
|
||||
final short partitionBufferSz = (2 * u16Size);
|
||||
final short partitionEntrySz = (3 * u16Size);
|
||||
@@ -120,16 +121,18 @@ public interface XmlToBinInterface
|
||||
final short vlanBufferSz = (2 * u16Size);
|
||||
final short vlanEntrySz = (2 * u16Size);
|
||||
|
||||
final short binaryBufferHeaderSz = (3 * u32Size + 4* u16Size);
|
||||
|
||||
/* copied directlty from policy_ops.h */
|
||||
final int POLICY_INTERFACE_VERSION = 0xAAAA0003;
|
||||
final int binaryBufferHeaderSz = (8 * u32Size); /* 8th not used in Xen */
|
||||
|
||||
/* copied directly from acm.h */
|
||||
final int ACM_MAGIC = 0x0001debc;
|
||||
final short ACM_NULL_POLICY = 0;
|
||||
final short ACM_CHINESE_WALL_POLICY = 1;
|
||||
final short ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY = 2;
|
||||
final short ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY = 3;
|
||||
final short ACM_EMPTY_POLICY = 4;
|
||||
final int ACM_NULL_POLICY = 0;
|
||||
final int ACM_CHINESE_WALL_POLICY = 1;
|
||||
final int ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY = 2;
|
||||
final int ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY = 3;
|
||||
final int ACM_EMPTY_POLICY = 4;
|
||||
|
||||
/* version for compatibility check */
|
||||
final int ACM_POLICY_VERSION = 1;
|
||||
final int ACM_STE_VERSION = 1;
|
||||
final int ACM_CHWALL_VERSION = 1;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/****************************************************************
|
||||
* c2j_include.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.
|
||||
*
|
||||
* This tool makes some constants from acm.h available to the
|
||||
* java policyprocessor for version checking.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
typedef int8_t s8;
|
||||
typedef int16_t s16;
|
||||
typedef int32_t s32;
|
||||
typedef int64_t s64;
|
||||
|
||||
#include <xen/acm.h>
|
||||
|
||||
char *filename = "policy_version.java";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
FILE *fd;
|
||||
if ((fd = fopen(filename, "w")) <= 0)
|
||||
{
|
||||
printf("File %s not found.\n", filename);
|
||||
exit(-ENOENT);
|
||||
}
|
||||
|
||||
fprintf(fd, "/*\n * This file was automatically generated\n");
|
||||
fprintf(fd, " * Do not change it manually!\n */\n");
|
||||
fprintf(fd, "public class policy_version {\n");
|
||||
fprintf(fd, " final int ACM_POLICY_VERSION = %x;\n",
|
||||
ACM_POLICY_VERSION);
|
||||
fprintf(fd, " final int ACM_CHWALL_VERSION = %x;\n",
|
||||
ACM_CHWALL_VERSION);
|
||||
fprintf(fd, " final int ACM_STE_VERSION = %x;\n",
|
||||
ACM_STE_VERSION);
|
||||
fprintf(fd, "}\n");
|
||||
fclose(fd);
|
||||
return 0;
|
||||
}
|
||||
@@ -37,7 +37,7 @@ xsi:schemaLocation="http://www.ibm.com SecurityPolicySpec.xsd">
|
||||
</ConflictSet>
|
||||
|
||||
<ConflictSet>
|
||||
<ChWall>Q-Company</ChWall>
|
||||
<ChWall>R-Company</ChWall>
|
||||
<ChWall>V-Company</ChWall>
|
||||
<ChWall>W-Company</ChWall>
|
||||
</ConflictSet>
|
||||
|
||||
@@ -1,552 +0,0 @@
|
||||
/****************************************************************
|
||||
* policy_tool.c
|
||||
*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Authors:
|
||||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
* Stefan Berger <stefanb@watson.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*
|
||||
* sHype policy management tool. This code runs in a domain and
|
||||
* manages the Xen security policy by interacting with the
|
||||
* Xen access control module via a /proc/xen/privcmd proc-ioctl,
|
||||
* which is translated into a policy_op hypercall into Xen.
|
||||
*
|
||||
* todo: implement setpolicy to dynamically set a policy cache.
|
||||
*/
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
typedef int8_t s8;
|
||||
typedef int16_t s16;
|
||||
typedef int32_t s32;
|
||||
typedef int64_t s64;
|
||||
|
||||
#include <xen/acm.h>
|
||||
|
||||
#include <xen/policy_ops.h>
|
||||
|
||||
#include <xen/linux/privcmd.h>
|
||||
|
||||
#define ERROR(_m, _a...) \
|
||||
fprintf(stderr, "ERROR: " _m "\n" , ## _a )
|
||||
|
||||
#define PERROR(_m, _a...) \
|
||||
fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
|
||||
errno, strerror(errno))
|
||||
|
||||
static inline int do_policycmd(int xc_handle,
|
||||
unsigned int cmd,
|
||||
unsigned long data)
|
||||
{
|
||||
return ioctl(xc_handle, cmd, data);
|
||||
}
|
||||
|
||||
static inline int do_xen_hypercall(int xc_handle,
|
||||
privcmd_hypercall_t *hypercall)
|
||||
{
|
||||
return do_policycmd(xc_handle,
|
||||
IOCTL_PRIVCMD_HYPERCALL,
|
||||
(unsigned long)hypercall);
|
||||
}
|
||||
|
||||
static inline int do_policy_op(int xc_handle, policy_op_t *op)
|
||||
{
|
||||
int ret = -1;
|
||||
privcmd_hypercall_t hypercall;
|
||||
|
||||
op->interface_version = POLICY_INTERFACE_VERSION;
|
||||
|
||||
hypercall.op = __HYPERVISOR_policy_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, "POLICY operation failed -- need to"
|
||||
" rebuild the user-space tool set?\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
out2: (void)munlock(op, sizeof(*op));
|
||||
out1: return ret;
|
||||
}
|
||||
|
||||
/*************************** DUMPS *******************************/
|
||||
|
||||
void acm_dump_chinesewall_buffer(void *buf, int buflen) {
|
||||
|
||||
struct acm_chwall_policy_buffer *cwbuf = (struct acm_chwall_policy_buffer *)buf;
|
||||
domaintype_t *ssids, *conflicts, *running_types, *conflict_aggregate;
|
||||
int i,j;
|
||||
|
||||
|
||||
if (htons(cwbuf->policy_code) != ACM_CHINESE_WALL_POLICY) {
|
||||
printf("CHINESE WALL POLICY CODE not found ERROR!!\n");
|
||||
return;
|
||||
}
|
||||
printf("\n\nChinese Wall policy:\n");
|
||||
printf("====================\n");
|
||||
printf("Max Types = %x.\n", ntohs(cwbuf->chwall_max_types));
|
||||
printf("Max Ssidrefs = %x.\n", ntohs(cwbuf->chwall_max_ssidrefs));
|
||||
printf("Max ConfSets = %x.\n", ntohs(cwbuf->chwall_max_conflictsets));
|
||||
printf("Ssidrefs Off = %x.\n", ntohs(cwbuf->chwall_ssid_offset));
|
||||
printf("Conflicts Off = %x.\n", ntohs(cwbuf->chwall_conflict_sets_offset));
|
||||
printf("Runing T. Off = %x.\n", ntohs(cwbuf->chwall_running_types_offset));
|
||||
printf("C. Agg. Off = %x.\n", ntohs(cwbuf->chwall_conflict_aggregate_offset));
|
||||
printf("\nSSID To CHWALL-Type matrix:\n");
|
||||
|
||||
ssids = (domaintype_t *)(buf + ntohs(cwbuf->chwall_ssid_offset));
|
||||
for(i=0; i< ntohs(cwbuf->chwall_max_ssidrefs); i++) {
|
||||
printf("\n ssidref%2x: ", i);
|
||||
for(j=0; j< ntohs(cwbuf->chwall_max_types); j++)
|
||||
printf("%02x ", ntohs(ssids[i*ntohs(cwbuf->chwall_max_types) + j]));
|
||||
}
|
||||
printf("\n\nConfict Sets:\n");
|
||||
conflicts = (domaintype_t *)(buf + ntohs(cwbuf->chwall_conflict_sets_offset));
|
||||
for(i=0; i< ntohs(cwbuf->chwall_max_conflictsets); i++) {
|
||||
printf("\n c-set%2x: ", i);
|
||||
for(j=0; j< ntohs(cwbuf->chwall_max_types); j++)
|
||||
printf("%02x ", ntohs(conflicts[i*ntohs(cwbuf->chwall_max_types) +j]));
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("\nRunning\nTypes: ");
|
||||
if (ntohs(cwbuf->chwall_running_types_offset)) {
|
||||
running_types = (domaintype_t *)(buf + ntohs(cwbuf->chwall_running_types_offset));
|
||||
for(i=0; i< ntohs(cwbuf->chwall_max_types); i++) {
|
||||
printf("%02x ", ntohs(running_types[i]));
|
||||
}
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("Not Reported!\n");
|
||||
}
|
||||
printf("\nConflict\nAggregate Set: ");
|
||||
if (ntohs(cwbuf->chwall_conflict_aggregate_offset)) {
|
||||
conflict_aggregate = (domaintype_t *)(buf + ntohs(cwbuf->chwall_conflict_aggregate_offset));
|
||||
for(i=0; i< ntohs(cwbuf->chwall_max_types); i++) {
|
||||
printf("%02x ", ntohs(conflict_aggregate[i]));
|
||||
}
|
||||
printf("\n\n");
|
||||
} else {
|
||||
printf("Not Reported!\n");
|
||||
}
|
||||
}
|
||||
|
||||
void acm_dump_ste_buffer(void *buf, int buflen) {
|
||||
|
||||
struct acm_ste_policy_buffer *stebuf = (struct acm_ste_policy_buffer *)buf;
|
||||
domaintype_t *ssids;
|
||||
int i,j;
|
||||
|
||||
|
||||
if (ntohs(stebuf->policy_code) != ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
|
||||
printf("SIMPLE TYPE ENFORCEMENT POLICY CODE not found ERROR!!\n");
|
||||
return;
|
||||
}
|
||||
printf("\nSimple Type Enforcement policy:\n");
|
||||
printf("===============================\n");
|
||||
printf("Max Types = %x.\n", ntohs(stebuf->ste_max_types));
|
||||
printf("Max Ssidrefs = %x.\n", ntohs(stebuf->ste_max_ssidrefs));
|
||||
printf("Ssidrefs Off = %x.\n", ntohs(stebuf->ste_ssid_offset));
|
||||
printf("\nSSID To STE-Type matrix:\n");
|
||||
|
||||
ssids = (domaintype_t *)(buf + ntohs(stebuf->ste_ssid_offset));
|
||||
for(i=0; i< ntohs(stebuf->ste_max_ssidrefs); i++) {
|
||||
printf("\n ssidref%2x: ", i);
|
||||
for(j=0; j< ntohs(stebuf->ste_max_types); j++)
|
||||
printf("%02x ", ntohs(ssids[i*ntohs(stebuf->ste_max_types) +j]));
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
void acm_dump_policy_buffer(void *buf, int buflen) {
|
||||
struct acm_policy_buffer *pol = (struct acm_policy_buffer *)buf;
|
||||
|
||||
printf("\nPolicy dump:\n");
|
||||
printf("============\n");
|
||||
printf("Magic = %x.\n", ntohl(pol->magic));
|
||||
printf("PolVer = %x.\n", ntohl(pol->policyversion));
|
||||
printf("Len = %x.\n", ntohl(pol->len));
|
||||
printf("Primary = %s (c=%x, off=%x).\n",
|
||||
ACM_POLICY_NAME(ntohs(pol->primary_policy_code)),
|
||||
ntohs(pol->primary_policy_code), ntohs(pol->primary_buffer_offset));
|
||||
printf("Secondary = %s (c=%x, off=%x).\n",
|
||||
ACM_POLICY_NAME(ntohs(pol->secondary_policy_code)),
|
||||
ntohs(pol->secondary_policy_code), ntohs(pol->secondary_buffer_offset));
|
||||
switch (ntohs(pol->primary_policy_code)) {
|
||||
case ACM_CHINESE_WALL_POLICY:
|
||||
acm_dump_chinesewall_buffer(buf+ntohs(pol->primary_buffer_offset),
|
||||
ntohl(pol->len) - ntohs(pol->primary_buffer_offset));
|
||||
break;
|
||||
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
|
||||
acm_dump_ste_buffer(buf+ntohs(pol->primary_buffer_offset),
|
||||
ntohl(pol->len) - ntohs(pol->primary_buffer_offset));
|
||||
break;
|
||||
case ACM_NULL_POLICY:
|
||||
printf("Primary policy is NULL Policy (n/a).\n");
|
||||
break;
|
||||
default:
|
||||
printf("UNKNOWN POLICY!\n");
|
||||
}
|
||||
switch (ntohs(pol->secondary_policy_code)) {
|
||||
case ACM_CHINESE_WALL_POLICY:
|
||||
acm_dump_chinesewall_buffer(buf+ntohs(pol->secondary_buffer_offset),
|
||||
ntohl(pol->len) - ntohs(pol->secondary_buffer_offset));
|
||||
break;
|
||||
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
|
||||
acm_dump_ste_buffer(buf+ntohs(pol->secondary_buffer_offset),
|
||||
ntohl(pol->len) - ntohs(pol->secondary_buffer_offset));
|
||||
break;
|
||||
case ACM_NULL_POLICY:
|
||||
printf("Secondary policy is NULL Policy (n/a).\n");
|
||||
break;
|
||||
default:
|
||||
printf("UNKNOWN POLICY!\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*************************** set policy ****************************/
|
||||
|
||||
int acm_domain_set_chwallpolicy(void *bufstart, int buflen) {
|
||||
#define CWALL_MAX_SSIDREFS 6
|
||||
#define CWALL_MAX_TYPES 10
|
||||
#define CWALL_MAX_CONFLICTSETS 2
|
||||
|
||||
struct acm_chwall_policy_buffer *chwall_bin_pol = (struct acm_chwall_policy_buffer *)bufstart;
|
||||
domaintype_t *ssidrefs, *conflicts;
|
||||
int ret = 0;
|
||||
int j;
|
||||
|
||||
chwall_bin_pol->chwall_max_types = htons(CWALL_MAX_TYPES);
|
||||
chwall_bin_pol->chwall_max_ssidrefs = htons(CWALL_MAX_SSIDREFS);
|
||||
chwall_bin_pol->policy_code = htons(ACM_CHINESE_WALL_POLICY);
|
||||
chwall_bin_pol->chwall_ssid_offset = htons(sizeof(struct acm_chwall_policy_buffer));
|
||||
chwall_bin_pol->chwall_max_conflictsets = htons(CWALL_MAX_CONFLICTSETS);
|
||||
chwall_bin_pol->chwall_conflict_sets_offset =
|
||||
htons(
|
||||
ntohs(chwall_bin_pol->chwall_ssid_offset) +
|
||||
sizeof(domaintype_t)*CWALL_MAX_SSIDREFS*CWALL_MAX_TYPES);
|
||||
chwall_bin_pol->chwall_running_types_offset = 0; /* not set */
|
||||
chwall_bin_pol->chwall_conflict_aggregate_offset = 0; /* not set */
|
||||
ret += sizeof(struct acm_chwall_policy_buffer);
|
||||
/* now push example ssids into the buffer (max_ssidrefs x max_types entries) */
|
||||
/* check buffer size */
|
||||
if ((buflen - ret) < (CWALL_MAX_TYPES*CWALL_MAX_SSIDREFS*sizeof(domaintype_t)))
|
||||
return -1; /* not enough space */
|
||||
|
||||
ssidrefs = (domaintype_t *)(bufstart+ntohs(chwall_bin_pol->chwall_ssid_offset));
|
||||
memset(ssidrefs, 0, CWALL_MAX_TYPES*CWALL_MAX_SSIDREFS*sizeof(domaintype_t));
|
||||
|
||||
/* now set type j-1 for ssidref i+1 */
|
||||
for(j=0; j<= CWALL_MAX_SSIDREFS; j++)
|
||||
if ((0 < j) &&( j <= CWALL_MAX_TYPES))
|
||||
ssidrefs[j*CWALL_MAX_TYPES + j - 1] = htons(1);
|
||||
|
||||
ret += CWALL_MAX_TYPES*CWALL_MAX_SSIDREFS*sizeof(domaintype_t);
|
||||
if ((buflen - ret) < (CWALL_MAX_CONFLICTSETS*CWALL_MAX_TYPES*sizeof(domaintype_t)))
|
||||
return -1; /* not enough space */
|
||||
|
||||
/* now the chinese wall policy conflict sets*/
|
||||
conflicts = (domaintype_t *)(bufstart +
|
||||
ntohs(chwall_bin_pol->chwall_conflict_sets_offset));
|
||||
memset((void *)conflicts, 0, CWALL_MAX_CONFLICTSETS*CWALL_MAX_TYPES*sizeof(domaintype_t));
|
||||
/* just 1 conflict set [0]={2,3}, [1]={1,5,6} */
|
||||
if (CWALL_MAX_TYPES > 3) {
|
||||
conflicts[2] = htons(1); conflicts[3] = htons(1); /* {2,3} */
|
||||
conflicts[CWALL_MAX_TYPES+1] = htons(1); conflicts[CWALL_MAX_TYPES+5] = htons(1);
|
||||
conflicts[CWALL_MAX_TYPES+6] = htons(1);/* {0,5,6} */
|
||||
}
|
||||
ret += sizeof(domaintype_t)*CWALL_MAX_CONFLICTSETS*CWALL_MAX_TYPES;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int acm_domain_set_stepolicy(void *bufstart, int buflen) {
|
||||
#define STE_MAX_SSIDREFS 6
|
||||
#define STE_MAX_TYPES 5
|
||||
|
||||
struct acm_ste_policy_buffer *ste_bin_pol = (struct acm_ste_policy_buffer *)bufstart;
|
||||
domaintype_t *ssidrefs;
|
||||
int j, ret = 0;
|
||||
|
||||
ste_bin_pol->ste_max_types = htons(STE_MAX_TYPES);
|
||||
ste_bin_pol->ste_max_ssidrefs = htons(STE_MAX_SSIDREFS);
|
||||
ste_bin_pol->policy_code = htons(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
|
||||
ste_bin_pol->ste_ssid_offset = htons(sizeof(struct acm_ste_policy_buffer));
|
||||
ret += sizeof(struct acm_ste_policy_buffer);
|
||||
/* check buffer size */
|
||||
if ((buflen - ret) < (STE_MAX_TYPES*STE_MAX_SSIDREFS*sizeof(domaintype_t)))
|
||||
return -1; /* not enough space */
|
||||
|
||||
ssidrefs = (domaintype_t *)(bufstart+ntohs(ste_bin_pol->ste_ssid_offset));
|
||||
memset(ssidrefs, 0, STE_MAX_TYPES*STE_MAX_SSIDREFS*sizeof(domaintype_t));
|
||||
/* all types 1 for ssidref 1 */
|
||||
for(j=0; j< STE_MAX_TYPES; j++)
|
||||
ssidrefs[1*STE_MAX_TYPES +j] = htons(1);
|
||||
/* now set type j-1 for ssidref j */
|
||||
for(j=0; j< STE_MAX_SSIDREFS; j++)
|
||||
if ((0 < j) &&( j <= STE_MAX_TYPES))
|
||||
ssidrefs[j*STE_MAX_TYPES + j - 1] = htons(1);
|
||||
ret += STE_MAX_TYPES*STE_MAX_SSIDREFS*sizeof(domaintype_t);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define MAX_PUSH_BUFFER 16384
|
||||
u8 push_buffer[MAX_PUSH_BUFFER];
|
||||
|
||||
int acm_domain_setpolicy(int xc_handle)
|
||||
{
|
||||
int ret;
|
||||
struct acm_policy_buffer *bin_pol;
|
||||
policy_op_t op;
|
||||
|
||||
/* future: read policy from file and set it */
|
||||
bin_pol = (struct acm_policy_buffer *)push_buffer;
|
||||
bin_pol->magic = htonl(ACM_MAGIC);
|
||||
bin_pol->policyversion = htonl(POLICY_INTERFACE_VERSION);
|
||||
bin_pol->primary_policy_code = htons(ACM_CHINESE_WALL_POLICY);
|
||||
bin_pol->secondary_policy_code = htons(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
|
||||
|
||||
bin_pol->len = htonl(sizeof(struct acm_policy_buffer));
|
||||
bin_pol->primary_buffer_offset = htons(ntohl(bin_pol->len));
|
||||
ret = acm_domain_set_chwallpolicy(push_buffer + ntohs(bin_pol->primary_buffer_offset),
|
||||
MAX_PUSH_BUFFER - ntohs(bin_pol->primary_buffer_offset));
|
||||
if (ret < 0) {
|
||||
printf("ERROR creating chwallpolicy buffer.\n");
|
||||
return -1;
|
||||
}
|
||||
bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
|
||||
bin_pol->secondary_buffer_offset = htons(ntohl(bin_pol->len));
|
||||
ret = acm_domain_set_stepolicy(push_buffer + ntohs(bin_pol->secondary_buffer_offset),
|
||||
MAX_PUSH_BUFFER - ntohs(bin_pol->secondary_buffer_offset));
|
||||
if (ret < 0) {
|
||||
printf("ERROR creating chwallpolicy buffer.\n");
|
||||
return -1;
|
||||
}
|
||||
bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
|
||||
|
||||
/* dump it and then push it down into xen/acm */
|
||||
acm_dump_policy_buffer(push_buffer, ntohl(bin_pol->len));
|
||||
op.cmd = POLICY_SETPOLICY;
|
||||
op.u.setpolicy.pushcache = (void *)push_buffer;
|
||||
op.u.setpolicy.pushcache_size = ntohl(bin_pol->len);
|
||||
op.u.setpolicy.policy_type = ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY;
|
||||
ret = do_policy_op(xc_handle, &op);
|
||||
|
||||
if (ret)
|
||||
printf("ERROR setting policy. Use 'xm dmesg' to see details.\n");
|
||||
else
|
||||
printf("Successfully changed policy.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************* get policy ******************************/
|
||||
|
||||
#define PULL_CACHE_SIZE 8192
|
||||
u8 pull_buffer[PULL_CACHE_SIZE];
|
||||
int acm_domain_getpolicy(int xc_handle)
|
||||
{
|
||||
policy_op_t op;
|
||||
int ret;
|
||||
|
||||
memset(pull_buffer, 0x00, sizeof(pull_buffer));
|
||||
op.cmd = POLICY_GETPOLICY;
|
||||
op.u.getpolicy.pullcache = (void *)pull_buffer;
|
||||
op.u.getpolicy.pullcache_size = sizeof(pull_buffer);
|
||||
ret = do_policy_op(xc_handle, &op);
|
||||
/* dump policy */
|
||||
acm_dump_policy_buffer(pull_buffer, sizeof(pull_buffer));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/************************ load binary policy ******************************/
|
||||
|
||||
int acm_domain_loadpolicy(int xc_handle,
|
||||
const char *filename)
|
||||
{
|
||||
struct stat mystat;
|
||||
int ret, fd;
|
||||
off_t len;
|
||||
u8 *buffer;
|
||||
|
||||
if ((ret = stat(filename, &mystat))) {
|
||||
printf("File %s not found.\n",filename);
|
||||
goto out;
|
||||
}
|
||||
|
||||
len = mystat.st_size;
|
||||
if ((buffer = malloc(len)) == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if ((fd = open(filename, O_RDONLY)) <= 0) {
|
||||
ret = -ENOENT;
|
||||
printf("File %s not found.\n",filename);
|
||||
goto free_out;
|
||||
}
|
||||
if (len == read(fd, buffer, len)) {
|
||||
policy_op_t op;
|
||||
/* dump it and then push it down into xen/acm */
|
||||
acm_dump_policy_buffer(buffer, len);
|
||||
op.cmd = POLICY_SETPOLICY;
|
||||
op.u.setpolicy.pushcache = (void *)buffer;
|
||||
op.u.setpolicy.pushcache_size = len;
|
||||
op.u.setpolicy.policy_type = ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY;
|
||||
ret = do_policy_op(xc_handle, &op);
|
||||
|
||||
if (ret)
|
||||
printf("ERROR setting policy. Use 'xm dmesg' to see details.\n");
|
||||
else
|
||||
printf("Successfully changed policy.\n");
|
||||
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
close(fd);
|
||||
free_out:
|
||||
free(buffer);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/************************ dump hook statistics ******************************/
|
||||
void
|
||||
dump_ste_stats(struct acm_ste_stats_buffer *ste_stats)
|
||||
{
|
||||
printf("STE-Policy Security Hook Statistics:\n");
|
||||
printf("ste: event_channel eval_count = %d\n", ntohl(ste_stats->ec_eval_count));
|
||||
printf("ste: event_channel denied_count = %d\n", ntohl(ste_stats->ec_denied_count));
|
||||
printf("ste: event_channel cache_hit_count = %d\n", ntohl(ste_stats->ec_cachehit_count));
|
||||
printf("ste:\n");
|
||||
printf("ste: grant_table eval_count = %d\n", ntohl(ste_stats->gt_eval_count));
|
||||
printf("ste: grant_table denied_count = %d\n", ntohl(ste_stats->gt_denied_count));
|
||||
printf("ste: grant_table cache_hit_count = %d\n", ntohl(ste_stats->gt_cachehit_count));
|
||||
}
|
||||
|
||||
#define PULL_STATS_SIZE 8192
|
||||
int acm_domain_dumpstats(int xc_handle)
|
||||
{
|
||||
u8 stats_buffer[PULL_STATS_SIZE];
|
||||
policy_op_t op;
|
||||
int ret;
|
||||
struct acm_stats_buffer *stats;
|
||||
|
||||
memset(stats_buffer, 0x00, sizeof(stats_buffer));
|
||||
op.cmd = POLICY_DUMPSTATS;
|
||||
op.u.dumpstats.pullcache = (void *)stats_buffer;
|
||||
op.u.dumpstats.pullcache_size = sizeof(stats_buffer);
|
||||
ret = do_policy_op(xc_handle, &op);
|
||||
|
||||
if (ret < 0) {
|
||||
printf("ERROR dumping policy stats. Use 'xm dmesg' to see details.\n");
|
||||
return ret;
|
||||
}
|
||||
stats = (struct acm_stats_buffer *)stats_buffer;
|
||||
|
||||
printf("\nPolicy dump:\n");
|
||||
printf("============\n");
|
||||
printf("Magic = %x.\n", ntohl(stats->magic));
|
||||
printf("PolVer = %x.\n", ntohl(stats->policyversion));
|
||||
printf("Len = %x.\n", ntohl(stats->len));
|
||||
|
||||
switch(ntohs(stats->primary_policy_code)) {
|
||||
case ACM_NULL_POLICY:
|
||||
printf("NULL Policy: No statistics apply.\n");
|
||||
break;
|
||||
case ACM_CHINESE_WALL_POLICY:
|
||||
printf("Chinese Wall Policy: No statistics apply.\n");
|
||||
break;
|
||||
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
|
||||
dump_ste_stats((struct acm_ste_stats_buffer *)(stats_buffer + ntohs(stats->primary_stats_offset)));
|
||||
break;
|
||||
default:
|
||||
printf("UNKNOWN PRIMARY POLICY ERROR!\n");
|
||||
}
|
||||
switch(ntohs(stats->secondary_policy_code)) {
|
||||
case ACM_NULL_POLICY:
|
||||
printf("NULL Policy: No statistics apply.\n");
|
||||
break;
|
||||
case ACM_CHINESE_WALL_POLICY:
|
||||
printf("Chinese Wall Policy: No statistics apply.\n");
|
||||
break;
|
||||
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
|
||||
dump_ste_stats((struct acm_ste_stats_buffer *)(stats_buffer + ntohs(stats->secondary_stats_offset)));
|
||||
break;
|
||||
default:
|
||||
printf("UNKNOWN SECONDARY POLICY ERROR!\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************** main **************************************/
|
||||
|
||||
void
|
||||
usage(char *progname){
|
||||
printf("Use: %s \n"
|
||||
"\t setpolicy\n"
|
||||
"\t getpolicy\n"
|
||||
"\t dumpstats\n"
|
||||
"\t loadpolicy <binary policy file>\n", progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv) {
|
||||
|
||||
int policycmd_fd, ret;
|
||||
|
||||
if (argc < 2)
|
||||
usage(argv[0]);
|
||||
|
||||
if ((policycmd_fd = open("/proc/xen/privcmd", O_RDONLY)) <= 0) {
|
||||
printf("ERROR: Could not open xen privcmd device!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "setpolicy")) {
|
||||
if (argc != 2)
|
||||
usage(argv[0]);
|
||||
ret = acm_domain_setpolicy(policycmd_fd);
|
||||
} else if (!strcmp(argv[1], "getpolicy")) {
|
||||
if (argc != 2)
|
||||
usage(argv[0]);
|
||||
ret = acm_domain_getpolicy(policycmd_fd);
|
||||
} else if (!strcmp(argv[1], "loadpolicy")) {
|
||||
if (argc != 3)
|
||||
usage(argv[0]);
|
||||
ret = acm_domain_loadpolicy(policycmd_fd, argv[2]);
|
||||
} else if (!strcmp(argv[1], "dumpstats")) {
|
||||
if (argc != 2)
|
||||
usage(argv[0]);
|
||||
ret = acm_domain_dumpstats(policycmd_fd);
|
||||
} else
|
||||
usage(argv[0]);
|
||||
|
||||
close(policycmd_fd);
|
||||
return ret;
|
||||
}
|
||||
@@ -23,7 +23,7 @@ if os.path.exists("/usr/include/reiserfs/reiserfs.h"):
|
||||
fsys_pkgs.append("grub.fsys.reiser")
|
||||
|
||||
setup(name='pygrub',
|
||||
version='0.2',
|
||||
version='0.3',
|
||||
description='Boot loader that looks a lot like grub for Xen',
|
||||
author='Jeremy Katz',
|
||||
author_email='katzj@redhat.com',
|
||||
|
||||
@@ -32,7 +32,7 @@ class Ext2FileSystemType(FileSystemType):
|
||||
def open_fs(self, fn, offset = 0):
|
||||
if not self.sniff_magic(fn, offset):
|
||||
raise ValueError, "Not an ext2 filesystem"
|
||||
return Ext2Fs(fn)
|
||||
return Ext2Fs(fn, offset = offset)
|
||||
|
||||
register_fstype(Ext2FileSystemType())
|
||||
|
||||
@@ -208,23 +208,29 @@ static PyObject *
|
||||
ext2_fs_open (Ext2Fs *fs, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = { "name", "flags", "superblock",
|
||||
"block_size", NULL };
|
||||
"block_size", "offset", NULL };
|
||||
char * name;
|
||||
int flags = 0, superblock = 0, err;
|
||||
int flags = 0, superblock = 0, offset = 0, err;
|
||||
unsigned int block_size = 0;
|
||||
ext2_filsys efs;
|
||||
char offsetopt[30];
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iii", kwlist,
|
||||
&name, &flags, &superblock, &block_size))
|
||||
return NULL;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iiii", kwlist,
|
||||
&name, &flags, &superblock,
|
||||
&block_size, &offset))
|
||||
return NULL;
|
||||
|
||||
if (fs->fs != NULL) {
|
||||
PyErr_SetString(PyExc_ValueError, "already have an fs object");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = ext2fs_open(name, flags, superblock, block_size,
|
||||
unix_io_manager, &efs);
|
||||
if (offset != 0) {
|
||||
snprintf(offsetopt, 29, "offset=%d", offset);
|
||||
}
|
||||
|
||||
err = ext2fs_open2(name, offsetopt, flags, superblock, block_size,
|
||||
unix_io_manager, &efs);
|
||||
if (err) {
|
||||
PyErr_SetString(PyExc_ValueError, "unable to open file");
|
||||
return NULL;
|
||||
@@ -323,14 +329,15 @@ static PyObject *
|
||||
ext2_fs_new(PyObject *o, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = { "name", "flags", "superblock",
|
||||
"block_size", NULL };
|
||||
"block_size", "offset", NULL };
|
||||
char * name;
|
||||
int flags = 0, superblock = 0;
|
||||
int flags = 0, superblock = 0, offset;
|
||||
unsigned int block_size = 0;
|
||||
Ext2Fs *pfs;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iii", kwlist,
|
||||
&name, &flags, &superblock, &block_size))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iiii", kwlist,
|
||||
&name, &flags, &superblock, &block_size,
|
||||
&offset))
|
||||
return NULL;
|
||||
|
||||
pfs = (Ext2Fs *) PyObject_NEW(Ext2Fs, &Ext2FsType);
|
||||
@@ -339,8 +346,8 @@ ext2_fs_new(PyObject *o, PyObject *args, PyObject *kwargs)
|
||||
pfs->fs = NULL;
|
||||
|
||||
if (!ext2_fs_open(pfs,
|
||||
Py_BuildValue("siii", name, flags, superblock, block_size),
|
||||
NULL))
|
||||
Py_BuildValue("siiii", name, flags, superblock,
|
||||
block_size, offset), NULL))
|
||||
return NULL;
|
||||
|
||||
return (PyObject *)pfs;
|
||||
|
||||
+26
-8
@@ -24,7 +24,7 @@ sys.path = [ '/usr/lib/python' ] + sys.path
|
||||
import grub.GrubConf
|
||||
import grub.fsys
|
||||
|
||||
PYGRUB_VER = 0.02
|
||||
PYGRUB_VER = 0.3
|
||||
|
||||
|
||||
def draw_window():
|
||||
@@ -77,24 +77,39 @@ def is_disk_image(file):
|
||||
buf = os.read(fd, 512)
|
||||
os.close(fd)
|
||||
|
||||
if len(buf) >= 512 and struct.unpack("H", buf[0x1fe: 0x200]) == (0xaaff):
|
||||
if len(buf) >= 512 and struct.unpack("H", buf[0x1fe: 0x200]) == (0xaa55,):
|
||||
return True
|
||||
return False
|
||||
|
||||
SECTOR_SIZE=512
|
||||
def get_active_offset(file):
|
||||
"""Find the offset for the start of the first active partition in the
|
||||
disk image file."""
|
||||
fd = os.open(file, os.O_RDONLY)
|
||||
buf = os.read(fd, 512)
|
||||
for poff in (446, 462, 478, 494): # partition offsets
|
||||
# active partition has 0x80 as the first byte
|
||||
if struct.unpack("<c", buf[p:p+1]) == ('\x80',):
|
||||
return struct.unpack("<", buf[p+8:p+12])[0] * SECTOR_SIZE
|
||||
return -1
|
||||
|
||||
def get_config(fn):
|
||||
if not os.access(fn, os.R_OK):
|
||||
raise RuntimeError, "Unable to access %s" %(fn,)
|
||||
|
||||
cf = grub.GrubConf.GrubConfigFile()
|
||||
|
||||
offset = 0
|
||||
if is_disk_image(fn):
|
||||
raise RuntimeError, "appears to be a full disk image... unable to handle this yet"
|
||||
offset = get_active_offset(fn)
|
||||
if offset == -1:
|
||||
raise RuntimeError, "Unable to find active partition on disk"
|
||||
|
||||
# open the image and read the grub config
|
||||
fs = None
|
||||
for fstype in grub.fsys.fstypes.values():
|
||||
if fstype.sniff_magic(fn):
|
||||
fs = fstype.open_fs(fn)
|
||||
if fstype.sniff_magic(fn, offset):
|
||||
fs = fstype.open_fs(fn, offset)
|
||||
break
|
||||
|
||||
if fs is not None:
|
||||
@@ -244,14 +259,17 @@ if __name__ == "__main__":
|
||||
if img.initrd:
|
||||
print " initrd: %s" %(img.initrd[1],)
|
||||
|
||||
offset = 0
|
||||
if is_disk_image(file):
|
||||
raise RuntimeError, "unable to handle full disk images yet"
|
||||
offset = get_active_offset(fn)
|
||||
if offset == -1:
|
||||
raise RuntimeError, "Unable to find active partition on disk"
|
||||
|
||||
# read the kernel and initrd onto the hostfs
|
||||
fs = None
|
||||
for fstype in grub.fsys.fstypes.values():
|
||||
if fstype.sniff_magic(file):
|
||||
fs = fstype.open_fs(file)
|
||||
if fstype.sniff_magic(file, offset):
|
||||
fs = fstype.open_fs(file, offset)
|
||||
break
|
||||
|
||||
if fs is None:
|
||||
|
||||
@@ -24,8 +24,8 @@ def blkdev_name_to_number(name):
|
||||
log.debug("exception looking up device number for %s: %s", name, ex)
|
||||
pass
|
||||
|
||||
if re.match( '/dev/sd[a-p]([0-9]|1[0-5])', n):
|
||||
return 8 * 256 + 16 * (ord(n[7:8]) - ord('a')) + int(n[8:])
|
||||
if re.match( '/dev/sd[a-p]([1-9]|1[0-5])?', n):
|
||||
return 8 * 256 + 16 * (ord(n[7:8]) - ord('a')) + int(n[8:] or 0)
|
||||
|
||||
if re.match( '/dev/hd[a-t]([1-9]|[1-5][0-9]|6[0-3])?', n):
|
||||
ide_majors = [ 3, 22, 33, 34, 56, 57, 88, 89, 90, 91 ]
|
||||
@@ -33,6 +33,9 @@ def blkdev_name_to_number(name):
|
||||
minor = ((ord(n[7:8]) - ord('a')) % 2) * 64 + int(n[8:] or 0)
|
||||
return major * 256 + minor
|
||||
|
||||
if re.match( '/dev/xvd[a-p]([1-9]|1[0-5])?', n):
|
||||
return 202 * 256 + 16 * (ord(n[8:9]) - ord('a')) + int(n[9:] or 0)
|
||||
|
||||
# see if this is a hex device number
|
||||
if re.match( '^(0x)?[0-9a-fA-F]+$', name ):
|
||||
return string.atoi(name,16)
|
||||
|
||||
@@ -152,6 +152,9 @@ class XendDomainInfo:
|
||||
vm = cls(db)
|
||||
vm.construct(config)
|
||||
vm.saveToDB(sync=True)
|
||||
# Flush info to xenstore immediately
|
||||
vm.exportToDB()
|
||||
|
||||
return vm
|
||||
|
||||
create = classmethod(create)
|
||||
@@ -172,6 +175,7 @@ class XendDomainInfo:
|
||||
log.debug('config=' + prettyprintstring(config))
|
||||
|
||||
vm.memory = info['mem_kb']/1024
|
||||
vm.target = info['mem_kb'] * 1024
|
||||
|
||||
if config:
|
||||
try:
|
||||
@@ -222,6 +226,7 @@ class XendDomainInfo:
|
||||
DBVar('restart_state', ty='str'),
|
||||
DBVar('restart_time', ty='float'),
|
||||
DBVar('restart_count', ty='int'),
|
||||
DBVar('target', ty='long', path="memory/target"),
|
||||
]
|
||||
|
||||
def __init__(self, db):
|
||||
@@ -240,6 +245,8 @@ class XendDomainInfo:
|
||||
self.ssidref = None
|
||||
self.image = None
|
||||
|
||||
self.target = None
|
||||
|
||||
self.channel = None
|
||||
self.store_channel = None
|
||||
self.store_mfn = None
|
||||
@@ -315,6 +322,7 @@ class XendDomainInfo:
|
||||
self.info = info
|
||||
self.memory = self.info['mem_kb'] / 1024
|
||||
self.ssidref = self.info['ssidref']
|
||||
self.target = self.info['mem_kb'] * 1024
|
||||
|
||||
def state_set(self, state):
|
||||
self.state_updated.acquire()
|
||||
@@ -399,7 +407,8 @@ class XendDomainInfo:
|
||||
['id', self.id],
|
||||
['name', self.name],
|
||||
['memory', self.memory],
|
||||
['ssidref', self.ssidref] ]
|
||||
['ssidref', self.ssidref],
|
||||
['target', self.target] ]
|
||||
if self.uuid:
|
||||
sxpr.append(['uuid', self.uuid])
|
||||
if self.info:
|
||||
@@ -536,6 +545,7 @@ class XendDomainInfo:
|
||||
self.memory = int(sxp.child_value(config, 'memory'))
|
||||
if self.memory is None:
|
||||
raise VmError('missing memory size')
|
||||
self.target = self.memory * (1 << 20)
|
||||
self.ssidref = int(sxp.child_value(config, 'ssidref'))
|
||||
cpu = sxp.child_value(config, 'cpu')
|
||||
if self.recreate and self.id and cpu is not None and int(cpu) >= 0:
|
||||
@@ -947,11 +957,12 @@ class XendDomainInfo:
|
||||
index[field_name] = field_index + 1
|
||||
|
||||
def mem_target_set(self, target):
|
||||
"""Set domain memory target in pages.
|
||||
"""Set domain memory target in bytes.
|
||||
"""
|
||||
if self.channel:
|
||||
msg = messages.packMsg('mem_request_t', { 'target' : target * (1 << 8)} )
|
||||
self.channel.writeRequest(msg)
|
||||
if target:
|
||||
self.target = target * (1 << 20)
|
||||
# Commit to XenStore immediately
|
||||
self.exportToDB()
|
||||
|
||||
def vcpu_hotplug(self, vcpu, state):
|
||||
"""Disable or enable VCPU in domain.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
XEN_ROOT = ../..
|
||||
include $(XEN_ROOT)/tools/Rules.mk
|
||||
|
||||
SRCS = policy_tool.c
|
||||
SRCS = secpol_tool.c
|
||||
CFLAGS += -static
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Werror
|
||||
@@ -11,17 +11,17 @@ CFLAGS += -I.
|
||||
|
||||
all: build
|
||||
build: mk-symlinks
|
||||
$(MAKE) policy_tool
|
||||
$(MAKE) secpol_tool
|
||||
|
||||
default: all
|
||||
|
||||
install: all
|
||||
|
||||
policy_tool : policy_tool.c
|
||||
secpol_tool : secpol_tool.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -rf policy_tool xen
|
||||
rm -rf secpol_tool xen
|
||||
|
||||
|
||||
LINUX_ROOT := $(XEN_ROOT)/linux-2.6-xen-sparse
|
||||
@@ -0,0 +1,648 @@
|
||||
/****************************************************************
|
||||
* secpol_tool.c
|
||||
*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Authors:
|
||||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
* Stefan Berger <stefanb@watson.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*
|
||||
* sHype policy management tool. This code runs in a domain and
|
||||
* manages the Xen security policy by interacting with the
|
||||
* Xen access control module via a /proc/xen/privcmd proc-ioctl,
|
||||
* which is translated into a acm_op hypercall into Xen.
|
||||
*
|
||||
* indent -i4 -kr -nut
|
||||
*/
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
typedef int8_t s8;
|
||||
typedef int16_t s16;
|
||||
typedef int32_t s32;
|
||||
typedef int64_t s64;
|
||||
|
||||
#include <xen/acm.h>
|
||||
#include <xen/acm_ops.h>
|
||||
#include <xen/linux/privcmd.h>
|
||||
|
||||
#define PERROR(_m, _a...) \
|
||||
fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
|
||||
errno, strerror(errno))
|
||||
|
||||
static inline int do_policycmd(int xc_handle, unsigned int cmd,
|
||||
unsigned long data)
|
||||
{
|
||||
return ioctl(xc_handle, cmd, data);
|
||||
}
|
||||
|
||||
static inline int do_xen_hypercall(int xc_handle,
|
||||
privcmd_hypercall_t * hypercall)
|
||||
{
|
||||
return do_policycmd(xc_handle,
|
||||
IOCTL_PRIVCMD_HYPERCALL,
|
||||
(unsigned long) hypercall);
|
||||
}
|
||||
|
||||
static inline int do_acm_op(int xc_handle, acm_op_t * op)
|
||||
{
|
||||
int ret = -1;
|
||||
privcmd_hypercall_t hypercall;
|
||||
|
||||
op->interface_version = ACM_INTERFACE_VERSION;
|
||||
|
||||
hypercall.op = __HYPERVISOR_acm_op;
|
||||
hypercall.arg[0] = (unsigned long) op;
|
||||
|
||||
if (mlock(op, sizeof(*op)) != 0)
|
||||
{
|
||||
PERROR("Could not lock memory for Xen policy hypercall");
|
||||
goto out1;
|
||||
}
|
||||
|
||||
if ((ret = do_xen_hypercall(xc_handle, &hypercall)) < 0)
|
||||
{
|
||||
if (errno == EACCES)
|
||||
fprintf(stderr, "ACM operation failed -- need to"
|
||||
" rebuild the user-space tool set?\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
out2:(void) munlock(op, sizeof(*op));
|
||||
out1:return ret;
|
||||
}
|
||||
|
||||
/*************************** DUMPS *******************************/
|
||||
|
||||
void acm_dump_chinesewall_buffer(void *buf, int buflen)
|
||||
{
|
||||
|
||||
struct acm_chwall_policy_buffer *cwbuf =
|
||||
(struct acm_chwall_policy_buffer *) buf;
|
||||
domaintype_t *ssids, *conflicts, *running_types, *conflict_aggregate;
|
||||
int i, j;
|
||||
|
||||
|
||||
if (htonl(cwbuf->policy_code) != ACM_CHINESE_WALL_POLICY)
|
||||
{
|
||||
printf("CHINESE WALL POLICY CODE not found ERROR!!\n");
|
||||
return;
|
||||
}
|
||||
printf("\n\nChinese Wall policy:\n");
|
||||
printf("====================\n");
|
||||
printf("Policy version= %x.\n", ntohl(cwbuf->policy_version));
|
||||
printf("Max Types = %x.\n", ntohl(cwbuf->chwall_max_types));
|
||||
printf("Max Ssidrefs = %x.\n", ntohl(cwbuf->chwall_max_ssidrefs));
|
||||
printf("Max ConfSets = %x.\n", ntohl(cwbuf->chwall_max_conflictsets));
|
||||
printf("Ssidrefs Off = %x.\n", ntohl(cwbuf->chwall_ssid_offset));
|
||||
printf("Conflicts Off = %x.\n",
|
||||
ntohl(cwbuf->chwall_conflict_sets_offset));
|
||||
printf("Runing T. Off = %x.\n",
|
||||
ntohl(cwbuf->chwall_running_types_offset));
|
||||
printf("C. Agg. Off = %x.\n",
|
||||
ntohl(cwbuf->chwall_conflict_aggregate_offset));
|
||||
printf("\nSSID To CHWALL-Type matrix:\n");
|
||||
|
||||
ssids = (domaintype_t *) (buf + ntohl(cwbuf->chwall_ssid_offset));
|
||||
for (i = 0; i < ntohl(cwbuf->chwall_max_ssidrefs); i++)
|
||||
{
|
||||
printf("\n ssidref%2x: ", i);
|
||||
for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++)
|
||||
printf("%02x ",
|
||||
ntohs(ssids[i * ntohl(cwbuf->chwall_max_types) + j]));
|
||||
}
|
||||
printf("\n\nConfict Sets:\n");
|
||||
conflicts =
|
||||
(domaintype_t *) (buf + ntohl(cwbuf->chwall_conflict_sets_offset));
|
||||
for (i = 0; i < ntohl(cwbuf->chwall_max_conflictsets); i++)
|
||||
{
|
||||
printf("\n c-set%2x: ", i);
|
||||
for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++)
|
||||
printf("%02x ",
|
||||
ntohs(conflicts
|
||||
[i * ntohl(cwbuf->chwall_max_types) + j]));
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("\nRunning\nTypes: ");
|
||||
if (ntohl(cwbuf->chwall_running_types_offset))
|
||||
{
|
||||
running_types =
|
||||
(domaintype_t *) (buf +
|
||||
ntohl(cwbuf->chwall_running_types_offset));
|
||||
for (i = 0; i < ntohl(cwbuf->chwall_max_types); i++)
|
||||
{
|
||||
printf("%02x ", ntohs(running_types[i]));
|
||||
}
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("Not Reported!\n");
|
||||
}
|
||||
printf("\nConflict\nAggregate Set: ");
|
||||
if (ntohl(cwbuf->chwall_conflict_aggregate_offset))
|
||||
{
|
||||
conflict_aggregate =
|
||||
(domaintype_t *) (buf +
|
||||
ntohl(cwbuf->chwall_conflict_aggregate_offset));
|
||||
for (i = 0; i < ntohl(cwbuf->chwall_max_types); i++)
|
||||
{
|
||||
printf("%02x ", ntohs(conflict_aggregate[i]));
|
||||
}
|
||||
printf("\n\n");
|
||||
} else {
|
||||
printf("Not Reported!\n");
|
||||
}
|
||||
}
|
||||
|
||||
void acm_dump_ste_buffer(void *buf, int buflen)
|
||||
{
|
||||
|
||||
struct acm_ste_policy_buffer *stebuf =
|
||||
(struct acm_ste_policy_buffer *) buf;
|
||||
domaintype_t *ssids;
|
||||
int i, j;
|
||||
|
||||
|
||||
if (ntohl(stebuf->policy_code) != ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
|
||||
printf("SIMPLE TYPE ENFORCEMENT POLICY CODE not found ERROR!!\n");
|
||||
return;
|
||||
}
|
||||
printf("\nSimple Type Enforcement policy:\n");
|
||||
printf("===============================\n");
|
||||
printf("Policy version= %x.\n", ntohl(stebuf->policy_version));
|
||||
printf("Max Types = %x.\n", ntohl(stebuf->ste_max_types));
|
||||
printf("Max Ssidrefs = %x.\n", ntohl(stebuf->ste_max_ssidrefs));
|
||||
printf("Ssidrefs Off = %x.\n", ntohl(stebuf->ste_ssid_offset));
|
||||
printf("\nSSID To STE-Type matrix:\n");
|
||||
|
||||
ssids = (domaintype_t *) (buf + ntohl(stebuf->ste_ssid_offset));
|
||||
for (i = 0; i < ntohl(stebuf->ste_max_ssidrefs); i++)
|
||||
{
|
||||
printf("\n ssidref%2x: ", i);
|
||||
for (j = 0; j < ntohl(stebuf->ste_max_types); j++)
|
||||
printf("%02x ", ntohs(ssids[i * ntohl(stebuf->ste_max_types) + j]));
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
void acm_dump_policy_buffer(void *buf, int buflen)
|
||||
{
|
||||
struct acm_policy_buffer *pol = (struct acm_policy_buffer *) buf;
|
||||
|
||||
printf("\nPolicy dump:\n");
|
||||
printf("============\n");
|
||||
printf("PolicyVer = %x.\n", ntohl(pol->policy_version));
|
||||
printf("Magic = %x.\n", ntohl(pol->magic));
|
||||
printf("Len = %x.\n", ntohl(pol->len));
|
||||
printf("Primary = %s (c=%x, off=%x).\n",
|
||||
ACM_POLICY_NAME(ntohl(pol->primary_policy_code)),
|
||||
ntohl(pol->primary_policy_code),
|
||||
ntohl(pol->primary_buffer_offset));
|
||||
printf("Secondary = %s (c=%x, off=%x).\n",
|
||||
ACM_POLICY_NAME(ntohl(pol->secondary_policy_code)),
|
||||
ntohl(pol->secondary_policy_code),
|
||||
ntohl(pol->secondary_buffer_offset));
|
||||
switch (ntohl(pol->primary_policy_code))
|
||||
{
|
||||
case ACM_CHINESE_WALL_POLICY:
|
||||
acm_dump_chinesewall_buffer(buf +
|
||||
ntohl(pol->primary_buffer_offset),
|
||||
ntohl(pol->len) -
|
||||
ntohl(pol->primary_buffer_offset));
|
||||
break;
|
||||
|
||||
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
|
||||
acm_dump_ste_buffer(buf + ntohl(pol->primary_buffer_offset),
|
||||
ntohl(pol->len) -
|
||||
ntohl(pol->primary_buffer_offset));
|
||||
break;
|
||||
|
||||
case ACM_NULL_POLICY:
|
||||
printf("Primary policy is NULL Policy (n/a).\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("UNKNOWN POLICY!\n");
|
||||
}
|
||||
|
||||
switch (ntohl(pol->secondary_policy_code))
|
||||
{
|
||||
case ACM_CHINESE_WALL_POLICY:
|
||||
acm_dump_chinesewall_buffer(buf +
|
||||
ntohl(pol->secondary_buffer_offset),
|
||||
ntohl(pol->len) -
|
||||
ntohl(pol->secondary_buffer_offset));
|
||||
break;
|
||||
|
||||
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
|
||||
acm_dump_ste_buffer(buf + ntohl(pol->secondary_buffer_offset),
|
||||
ntohl(pol->len) -
|
||||
ntohl(pol->secondary_buffer_offset));
|
||||
break;
|
||||
|
||||
case ACM_NULL_POLICY:
|
||||
printf("Secondary policy is NULL Policy (n/a).\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("UNKNOWN POLICY!\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*************************** set policy ****************************/
|
||||
|
||||
int acm_domain_set_chwallpolicy(void *bufstart, int buflen)
|
||||
{
|
||||
#define CWALL_MAX_SSIDREFS 6
|
||||
#define CWALL_MAX_TYPES 10
|
||||
#define CWALL_MAX_CONFLICTSETS 2
|
||||
|
||||
struct acm_chwall_policy_buffer *chwall_bin_pol =
|
||||
(struct acm_chwall_policy_buffer *) bufstart;
|
||||
domaintype_t *ssidrefs, *conflicts;
|
||||
int ret = 0;
|
||||
int j;
|
||||
|
||||
chwall_bin_pol->chwall_max_types = htonl(CWALL_MAX_TYPES);
|
||||
chwall_bin_pol->chwall_max_ssidrefs = htonl(CWALL_MAX_SSIDREFS);
|
||||
chwall_bin_pol->policy_code = htonl(ACM_CHINESE_WALL_POLICY);
|
||||
chwall_bin_pol->policy_version = htonl(ACM_CHWALL_VERSION);
|
||||
chwall_bin_pol->chwall_ssid_offset =
|
||||
htonl(sizeof(struct acm_chwall_policy_buffer));
|
||||
chwall_bin_pol->chwall_max_conflictsets =
|
||||
htonl(CWALL_MAX_CONFLICTSETS);
|
||||
chwall_bin_pol->chwall_conflict_sets_offset =
|
||||
htonl(ntohl(chwall_bin_pol->chwall_ssid_offset) +
|
||||
sizeof(domaintype_t) * CWALL_MAX_SSIDREFS * CWALL_MAX_TYPES);
|
||||
chwall_bin_pol->chwall_running_types_offset = 0; /* not set */
|
||||
chwall_bin_pol->chwall_conflict_aggregate_offset = 0; /* not set */
|
||||
ret += sizeof(struct acm_chwall_policy_buffer);
|
||||
/* now push example ssids into the buffer (max_ssidrefs x max_types entries) */
|
||||
/* check buffer size */
|
||||
if ((buflen - ret) <
|
||||
(CWALL_MAX_TYPES * CWALL_MAX_SSIDREFS * sizeof(domaintype_t)))
|
||||
return -1; /* not enough space */
|
||||
|
||||
ssidrefs = (domaintype_t *) (bufstart +
|
||||
ntohl(chwall_bin_pol->chwall_ssid_offset));
|
||||
memset(ssidrefs, 0,
|
||||
CWALL_MAX_TYPES * CWALL_MAX_SSIDREFS * sizeof(domaintype_t));
|
||||
|
||||
/* now set type j-1 for ssidref i+1 */
|
||||
for (j = 0; j <= CWALL_MAX_SSIDREFS; j++)
|
||||
if ((0 < j) && (j <= CWALL_MAX_TYPES))
|
||||
ssidrefs[j * CWALL_MAX_TYPES + j - 1] = htons(1);
|
||||
|
||||
ret += CWALL_MAX_TYPES * CWALL_MAX_SSIDREFS * sizeof(domaintype_t);
|
||||
if ((buflen - ret) <
|
||||
(CWALL_MAX_CONFLICTSETS * CWALL_MAX_TYPES * sizeof(domaintype_t)))
|
||||
return -1; /* not enough space */
|
||||
|
||||
/* now the chinese wall policy conflict sets */
|
||||
conflicts = (domaintype_t *) (bufstart +
|
||||
ntohl(chwall_bin_pol->
|
||||
chwall_conflict_sets_offset));
|
||||
memset((void *) conflicts, 0,
|
||||
CWALL_MAX_CONFLICTSETS * CWALL_MAX_TYPES *
|
||||
sizeof(domaintype_t));
|
||||
/* just 1 conflict set [0]={2,3}, [1]={1,5,6} */
|
||||
if (CWALL_MAX_TYPES > 3)
|
||||
{
|
||||
conflicts[2] = htons(1);
|
||||
conflicts[3] = htons(1); /* {2,3} */
|
||||
conflicts[CWALL_MAX_TYPES + 1] = htons(1);
|
||||
conflicts[CWALL_MAX_TYPES + 5] = htons(1);
|
||||
conflicts[CWALL_MAX_TYPES + 6] = htons(1); /* {0,5,6} */
|
||||
}
|
||||
ret += sizeof(domaintype_t) * CWALL_MAX_CONFLICTSETS * CWALL_MAX_TYPES;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int acm_domain_set_stepolicy(void *bufstart, int buflen)
|
||||
{
|
||||
#define STE_MAX_SSIDREFS 6
|
||||
#define STE_MAX_TYPES 5
|
||||
|
||||
struct acm_ste_policy_buffer *ste_bin_pol =
|
||||
(struct acm_ste_policy_buffer *) bufstart;
|
||||
domaintype_t *ssidrefs;
|
||||
int j, ret = 0;
|
||||
|
||||
ste_bin_pol->ste_max_types = htonl(STE_MAX_TYPES);
|
||||
ste_bin_pol->ste_max_ssidrefs = htonl(STE_MAX_SSIDREFS);
|
||||
ste_bin_pol->policy_code = htonl(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
|
||||
ste_bin_pol->policy_version = htonl(ACM_STE_VERSION);
|
||||
ste_bin_pol->ste_ssid_offset =
|
||||
htonl(sizeof(struct acm_ste_policy_buffer));
|
||||
ret += sizeof(struct acm_ste_policy_buffer);
|
||||
/* check buffer size */
|
||||
if ((buflen - ret) <
|
||||
(STE_MAX_TYPES * STE_MAX_SSIDREFS * sizeof(domaintype_t)))
|
||||
return -1; /* not enough space */
|
||||
|
||||
ssidrefs =
|
||||
(domaintype_t *) (bufstart + ntohl(ste_bin_pol->ste_ssid_offset));
|
||||
memset(ssidrefs, 0,
|
||||
STE_MAX_TYPES * STE_MAX_SSIDREFS * sizeof(domaintype_t));
|
||||
/* all types 1 for ssidref 1 */
|
||||
for (j = 0; j < STE_MAX_TYPES; j++)
|
||||
ssidrefs[1 * STE_MAX_TYPES + j] = htons(1);
|
||||
/* now set type j-1 for ssidref j */
|
||||
for (j = 0; j < STE_MAX_SSIDREFS; j++)
|
||||
if ((0 < j) && (j <= STE_MAX_TYPES))
|
||||
ssidrefs[j * STE_MAX_TYPES + j - 1] = htons(1);
|
||||
ret += STE_MAX_TYPES * STE_MAX_SSIDREFS * sizeof(domaintype_t);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define MAX_PUSH_BUFFER 16384
|
||||
u8 push_buffer[MAX_PUSH_BUFFER];
|
||||
|
||||
int acm_domain_setpolicy(int xc_handle)
|
||||
{
|
||||
int ret;
|
||||
struct acm_policy_buffer *bin_pol;
|
||||
acm_op_t op;
|
||||
|
||||
/* future: read policy from file and set it */
|
||||
bin_pol = (struct acm_policy_buffer *) push_buffer;
|
||||
bin_pol->policy_version = htonl(ACM_POLICY_VERSION);
|
||||
bin_pol->magic = htonl(ACM_MAGIC);
|
||||
bin_pol->primary_policy_code = htonl(ACM_CHINESE_WALL_POLICY);
|
||||
bin_pol->secondary_policy_code =
|
||||
htonl(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
|
||||
|
||||
bin_pol->len = htonl(sizeof(struct acm_policy_buffer));
|
||||
bin_pol->primary_buffer_offset = htonl(ntohl(bin_pol->len));
|
||||
ret =
|
||||
acm_domain_set_chwallpolicy(push_buffer +
|
||||
ntohl(bin_pol->primary_buffer_offset),
|
||||
MAX_PUSH_BUFFER -
|
||||
ntohl(bin_pol->primary_buffer_offset));
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("ERROR creating chwallpolicy buffer.\n");
|
||||
return -1;
|
||||
}
|
||||
bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
|
||||
bin_pol->secondary_buffer_offset = htonl(ntohl(bin_pol->len));
|
||||
ret = acm_domain_set_stepolicy(push_buffer +
|
||||
ntohl(bin_pol->secondary_buffer_offset),
|
||||
MAX_PUSH_BUFFER -
|
||||
ntohl(bin_pol->secondary_buffer_offset));
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("ERROR creating chwallpolicy buffer.\n");
|
||||
return -1;
|
||||
}
|
||||
bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
|
||||
|
||||
/* dump it and then push it down into xen/acm */
|
||||
acm_dump_policy_buffer(push_buffer, ntohl(bin_pol->len));
|
||||
|
||||
op.cmd = ACM_SETPOLICY;
|
||||
op.interface_version = ACM_INTERFACE_VERSION;
|
||||
op.u.setpolicy.pushcache = (void *) push_buffer;
|
||||
op.u.setpolicy.pushcache_size = ntohl(bin_pol->len);
|
||||
ret = do_acm_op(xc_handle, &op);
|
||||
|
||||
if (ret)
|
||||
printf("ERROR setting policy. Use 'xm dmesg' to see details.\n");
|
||||
else
|
||||
printf("Successfully changed policy.\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************* get policy ******************************/
|
||||
|
||||
#define PULL_CACHE_SIZE 8192
|
||||
u8 pull_buffer[PULL_CACHE_SIZE];
|
||||
int acm_domain_getpolicy(int xc_handle)
|
||||
{
|
||||
acm_op_t op;
|
||||
int ret;
|
||||
|
||||
memset(pull_buffer, 0x00, sizeof(pull_buffer));
|
||||
op.cmd = ACM_GETPOLICY;
|
||||
op.interface_version = ACM_INTERFACE_VERSION;
|
||||
op.u.getpolicy.pullcache = (void *) pull_buffer;
|
||||
op.u.getpolicy.pullcache_size = sizeof(pull_buffer);
|
||||
ret = do_acm_op(xc_handle, &op);
|
||||
/* dump policy */
|
||||
acm_dump_policy_buffer(pull_buffer, sizeof(pull_buffer));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/************************ load binary policy ******************************/
|
||||
|
||||
int acm_domain_loadpolicy(int xc_handle, const char *filename)
|
||||
{
|
||||
struct stat mystat;
|
||||
int ret, fd;
|
||||
off_t len;
|
||||
u8 *buffer;
|
||||
|
||||
if ((ret = stat(filename, &mystat)))
|
||||
{
|
||||
printf("File %s not found.\n", filename);
|
||||
goto out;
|
||||
}
|
||||
|
||||
len = mystat.st_size;
|
||||
if ((buffer = malloc(len)) == NULL)
|
||||
{
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if ((fd = open(filename, O_RDONLY)) <= 0)
|
||||
{
|
||||
ret = -ENOENT;
|
||||
printf("File %s not found.\n", filename);
|
||||
goto free_out;
|
||||
}
|
||||
if (len == read(fd, buffer, len))
|
||||
{
|
||||
acm_op_t op;
|
||||
/* dump it and then push it down into xen/acm */
|
||||
acm_dump_policy_buffer(buffer, len);
|
||||
op.cmd = ACM_SETPOLICY;
|
||||
op.interface_version = ACM_INTERFACE_VERSION;
|
||||
op.u.setpolicy.pushcache = (void *) buffer;
|
||||
op.u.setpolicy.pushcache_size = len;
|
||||
ret = do_acm_op(xc_handle, &op);
|
||||
|
||||
if (ret)
|
||||
printf
|
||||
("ERROR setting policy. Use 'xm dmesg' to see details.\n");
|
||||
else
|
||||
printf("Successfully changed policy.\n");
|
||||
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
close(fd);
|
||||
free_out:
|
||||
free(buffer);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/************************ dump hook statistics ******************************/
|
||||
void dump_ste_stats(struct acm_ste_stats_buffer *ste_stats)
|
||||
{
|
||||
printf("STE-Policy Security Hook Statistics:\n");
|
||||
printf("ste: event_channel eval_count = %d\n",
|
||||
ntohl(ste_stats->ec_eval_count));
|
||||
printf("ste: event_channel denied_count = %d\n",
|
||||
ntohl(ste_stats->ec_denied_count));
|
||||
printf("ste: event_channel cache_hit_count = %d\n",
|
||||
ntohl(ste_stats->ec_cachehit_count));
|
||||
printf("ste:\n");
|
||||
printf("ste: grant_table eval_count = %d\n",
|
||||
ntohl(ste_stats->gt_eval_count));
|
||||
printf("ste: grant_table denied_count = %d\n",
|
||||
ntohl(ste_stats->gt_denied_count));
|
||||
printf("ste: grant_table cache_hit_count = %d\n",
|
||||
ntohl(ste_stats->gt_cachehit_count));
|
||||
}
|
||||
|
||||
#define PULL_STATS_SIZE 8192
|
||||
int acm_domain_dumpstats(int xc_handle)
|
||||
{
|
||||
u8 stats_buffer[PULL_STATS_SIZE];
|
||||
acm_op_t op;
|
||||
int ret;
|
||||
struct acm_stats_buffer *stats;
|
||||
|
||||
memset(stats_buffer, 0x00, sizeof(stats_buffer));
|
||||
op.cmd = ACM_DUMPSTATS;
|
||||
op.interface_version = ACM_INTERFACE_VERSION;
|
||||
op.u.dumpstats.pullcache = (void *) stats_buffer;
|
||||
op.u.dumpstats.pullcache_size = sizeof(stats_buffer);
|
||||
ret = do_acm_op(xc_handle, &op);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("ERROR dumping policy stats. Use 'xm dmesg' to see details.\n");
|
||||
return ret;
|
||||
}
|
||||
stats = (struct acm_stats_buffer *) stats_buffer;
|
||||
|
||||
printf("\nPolicy dump:\n");
|
||||
printf("============\n");
|
||||
printf("Magic = %x.\n", ntohl(stats->magic));
|
||||
printf("Len = %x.\n", ntohl(stats->len));
|
||||
|
||||
switch (ntohl(stats->primary_policy_code))
|
||||
{
|
||||
case ACM_NULL_POLICY:
|
||||
printf("NULL Policy: No statistics apply.\n");
|
||||
break;
|
||||
|
||||
case ACM_CHINESE_WALL_POLICY:
|
||||
printf("Chinese Wall Policy: No statistics apply.\n");
|
||||
break;
|
||||
|
||||
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
|
||||
dump_ste_stats((struct acm_ste_stats_buffer *) (stats_buffer +
|
||||
ntohl(stats->
|
||||
primary_stats_offset)));
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("UNKNOWN PRIMARY POLICY ERROR!\n");
|
||||
}
|
||||
|
||||
switch (ntohl(stats->secondary_policy_code))
|
||||
{
|
||||
case ACM_NULL_POLICY:
|
||||
printf("NULL Policy: No statistics apply.\n");
|
||||
break;
|
||||
|
||||
case ACM_CHINESE_WALL_POLICY:
|
||||
printf("Chinese Wall Policy: No statistics apply.\n");
|
||||
break;
|
||||
|
||||
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
|
||||
dump_ste_stats((struct acm_ste_stats_buffer *) (stats_buffer +
|
||||
ntohl(stats->
|
||||
secondary_stats_offset)));
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("UNKNOWN SECONDARY POLICY ERROR!\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************** main **************************************/
|
||||
|
||||
void usage(char *progname)
|
||||
{
|
||||
printf("Use: %s \n"
|
||||
"\t setpolicy\n"
|
||||
"\t getpolicy\n"
|
||||
"\t dumpstats\n"
|
||||
"\t loadpolicy <binary policy file>\n", progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
int acm_cmd_fd, ret;
|
||||
|
||||
if (argc < 2)
|
||||
usage(argv[0]);
|
||||
|
||||
if ((acm_cmd_fd = open("/proc/xen/privcmd", O_RDONLY)) <= 0)
|
||||
{
|
||||
printf("ERROR: Could not open xen privcmd device!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "setpolicy"))
|
||||
{
|
||||
if (argc != 2)
|
||||
usage(argv[0]);
|
||||
ret = acm_domain_setpolicy(acm_cmd_fd);
|
||||
} else if (!strcmp(argv[1], "getpolicy")) {
|
||||
if (argc != 2)
|
||||
usage(argv[0]);
|
||||
ret = acm_domain_getpolicy(acm_cmd_fd);
|
||||
} else if (!strcmp(argv[1], "loadpolicy")) {
|
||||
if (argc != 3)
|
||||
usage(argv[0]);
|
||||
ret = acm_domain_loadpolicy(acm_cmd_fd, argv[2]);
|
||||
} else if (!strcmp(argv[1], "dumpstats")) {
|
||||
if (argc != 2)
|
||||
usage(argv[0]);
|
||||
ret = acm_domain_dumpstats(acm_cmd_fd);
|
||||
} else
|
||||
usage(argv[0]);
|
||||
|
||||
close(acm_cmd_fd);
|
||||
return ret;
|
||||
}
|
||||
@@ -110,45 +110,45 @@ chwall_dump_policy(u8 *buf, u16 buf_size) {
|
||||
struct acm_chwall_policy_buffer *chwall_buf = (struct acm_chwall_policy_buffer *)buf;
|
||||
int ret = 0;
|
||||
|
||||
chwall_buf->chwall_max_types = htons(chwall_bin_pol.max_types);
|
||||
chwall_buf->chwall_max_ssidrefs = htons(chwall_bin_pol.max_ssidrefs);
|
||||
chwall_buf->policy_code = htons(ACM_CHINESE_WALL_POLICY);
|
||||
chwall_buf->chwall_ssid_offset = htons(sizeof(struct acm_chwall_policy_buffer));
|
||||
chwall_buf->chwall_max_conflictsets = htons(chwall_bin_pol.max_conflictsets);
|
||||
chwall_buf->chwall_max_types = htonl(chwall_bin_pol.max_types);
|
||||
chwall_buf->chwall_max_ssidrefs = htonl(chwall_bin_pol.max_ssidrefs);
|
||||
chwall_buf->policy_code = htonl(ACM_CHINESE_WALL_POLICY);
|
||||
chwall_buf->chwall_ssid_offset = htonl(sizeof(struct acm_chwall_policy_buffer));
|
||||
chwall_buf->chwall_max_conflictsets = htonl(chwall_bin_pol.max_conflictsets);
|
||||
chwall_buf->chwall_conflict_sets_offset =
|
||||
htons(
|
||||
ntohs(chwall_buf->chwall_ssid_offset) +
|
||||
htonl(
|
||||
ntohl(chwall_buf->chwall_ssid_offset) +
|
||||
sizeof(domaintype_t) * chwall_bin_pol.max_ssidrefs *
|
||||
chwall_bin_pol.max_types);
|
||||
|
||||
chwall_buf->chwall_running_types_offset =
|
||||
htons(
|
||||
ntohs(chwall_buf->chwall_conflict_sets_offset) +
|
||||
htonl(
|
||||
ntohl(chwall_buf->chwall_conflict_sets_offset) +
|
||||
sizeof(domaintype_t) * chwall_bin_pol.max_conflictsets *
|
||||
chwall_bin_pol.max_types);
|
||||
|
||||
chwall_buf->chwall_conflict_aggregate_offset =
|
||||
htons(
|
||||
ntohs(chwall_buf->chwall_running_types_offset) +
|
||||
htonl(
|
||||
ntohl(chwall_buf->chwall_running_types_offset) +
|
||||
sizeof(domaintype_t) * chwall_bin_pol.max_types);
|
||||
|
||||
ret = ntohs(chwall_buf->chwall_conflict_aggregate_offset) +
|
||||
ret = ntohl(chwall_buf->chwall_conflict_aggregate_offset) +
|
||||
sizeof(domaintype_t) * chwall_bin_pol.max_types;
|
||||
|
||||
/* now copy buffers over */
|
||||
arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_ssid_offset)),
|
||||
arrcpy16((u16 *)(buf + ntohl(chwall_buf->chwall_ssid_offset)),
|
||||
chwall_bin_pol.ssidrefs,
|
||||
chwall_bin_pol.max_ssidrefs * chwall_bin_pol.max_types);
|
||||
|
||||
arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_conflict_sets_offset)),
|
||||
arrcpy16((u16 *)(buf + ntohl(chwall_buf->chwall_conflict_sets_offset)),
|
||||
chwall_bin_pol.conflict_sets,
|
||||
chwall_bin_pol.max_conflictsets * chwall_bin_pol.max_types);
|
||||
|
||||
arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_running_types_offset)),
|
||||
arrcpy16((u16 *)(buf + ntohl(chwall_buf->chwall_running_types_offset)),
|
||||
chwall_bin_pol.running_types,
|
||||
chwall_bin_pol.max_types);
|
||||
|
||||
arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_conflict_aggregate_offset)),
|
||||
arrcpy16((u16 *)(buf + ntohl(chwall_buf->chwall_conflict_aggregate_offset)),
|
||||
chwall_bin_pol.conflict_aggregate_set,
|
||||
chwall_bin_pol.max_types);
|
||||
return ret;
|
||||
@@ -226,14 +226,20 @@ chwall_set_policy(u8 *buf, u16 buf_size)
|
||||
void *ssids = NULL, *conflict_sets = NULL, *running_types = NULL, *conflict_aggregate_set = NULL;
|
||||
|
||||
/* rewrite the policy due to endianess */
|
||||
chwall_buf->policy_code = ntohs(chwall_buf->policy_code);
|
||||
chwall_buf->chwall_max_types = ntohs(chwall_buf->chwall_max_types);
|
||||
chwall_buf->chwall_max_ssidrefs = ntohs(chwall_buf->chwall_max_ssidrefs);
|
||||
chwall_buf->chwall_max_conflictsets = ntohs(chwall_buf->chwall_max_conflictsets);
|
||||
chwall_buf->chwall_ssid_offset = ntohs(chwall_buf->chwall_ssid_offset);
|
||||
chwall_buf->chwall_conflict_sets_offset = ntohs(chwall_buf->chwall_conflict_sets_offset);
|
||||
chwall_buf->chwall_running_types_offset = ntohs(chwall_buf->chwall_running_types_offset);
|
||||
chwall_buf->chwall_conflict_aggregate_offset = ntohs(chwall_buf->chwall_conflict_aggregate_offset);
|
||||
chwall_buf->policy_code = ntohl(chwall_buf->policy_code);
|
||||
chwall_buf->policy_version = ntohl(chwall_buf->policy_version);
|
||||
chwall_buf->chwall_max_types = ntohl(chwall_buf->chwall_max_types);
|
||||
chwall_buf->chwall_max_ssidrefs = ntohl(chwall_buf->chwall_max_ssidrefs);
|
||||
chwall_buf->chwall_max_conflictsets = ntohl(chwall_buf->chwall_max_conflictsets);
|
||||
chwall_buf->chwall_ssid_offset = ntohl(chwall_buf->chwall_ssid_offset);
|
||||
chwall_buf->chwall_conflict_sets_offset = ntohl(chwall_buf->chwall_conflict_sets_offset);
|
||||
chwall_buf->chwall_running_types_offset = ntohl(chwall_buf->chwall_running_types_offset);
|
||||
chwall_buf->chwall_conflict_aggregate_offset = ntohl(chwall_buf->chwall_conflict_aggregate_offset);
|
||||
|
||||
/* policy type and version checks */
|
||||
if ((chwall_buf->policy_code != ACM_CHINESE_WALL_POLICY) ||
|
||||
(chwall_buf->policy_version != ACM_CHWALL_VERSION))
|
||||
return -EINVAL;
|
||||
|
||||
/* 1. allocate new buffers */
|
||||
ssids = xmalloc_array(domaintype_t, chwall_buf->chwall_max_types*chwall_buf->chwall_max_ssidrefs);
|
||||
|
||||
@@ -120,7 +120,6 @@ acm_setup(unsigned int *initrdidx,
|
||||
if (ntohl(pol->magic) == ACM_MAGIC) {
|
||||
rc = acm_set_policy((void *)_policy_start,
|
||||
(u16)_policy_len,
|
||||
ACM_USE_SECURITY_POLICY,
|
||||
0);
|
||||
if (rc == ACM_OK) {
|
||||
printf("Policy len 0x%lx, start at %p.\n",_policy_len,_policy_start);
|
||||
|
||||
+30
-44
@@ -6,9 +6,8 @@
|
||||
* Author:
|
||||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
*
|
||||
* Contributions:
|
||||
* Contributors:
|
||||
* Stefan Berger <stefanb@watson.ibm.com>
|
||||
* support for network-byte-order binary policies
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
@@ -27,29 +26,20 @@
|
||||
#include <xen/lib.h>
|
||||
#include <xen/delay.h>
|
||||
#include <xen/sched.h>
|
||||
#include <public/policy_ops.h>
|
||||
#include <public/acm_ops.h>
|
||||
#include <acm/acm_core.h>
|
||||
#include <acm/acm_hooks.h>
|
||||
#include <acm/acm_endian.h>
|
||||
|
||||
int
|
||||
acm_set_policy(void *buf, u16 buf_size, u16 policy, int isuserbuffer)
|
||||
acm_set_policy(void *buf, u16 buf_size, int isuserbuffer)
|
||||
{
|
||||
u8 *policy_buffer = NULL;
|
||||
struct acm_policy_buffer *pol;
|
||||
|
||||
if (policy != ACM_USE_SECURITY_POLICY) {
|
||||
printk("%s: Loading incompatible policy (running: %s).\n", __func__,
|
||||
ACM_POLICY_NAME(ACM_USE_SECURITY_POLICY));
|
||||
return -EFAULT;
|
||||
}
|
||||
/* now check correct buffer sizes for policy combinations */
|
||||
if (policy == ACM_NULL_POLICY) {
|
||||
printkd("%s: NULL Policy, no policy needed.\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (buf_size < sizeof(struct acm_policy_buffer))
|
||||
return -EFAULT;
|
||||
|
||||
/* 1. copy buffer from domain */
|
||||
if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL)
|
||||
goto error_free;
|
||||
@@ -58,17 +48,17 @@ acm_set_policy(void *buf, u16 buf_size, u16 policy, int isuserbuffer)
|
||||
printk("%s: Error copying!\n",__func__);
|
||||
goto error_free;
|
||||
}
|
||||
} else {
|
||||
} else
|
||||
memcpy(policy_buffer, buf, buf_size);
|
||||
}
|
||||
|
||||
/* 2. some sanity checking */
|
||||
pol = (struct acm_policy_buffer *)policy_buffer;
|
||||
|
||||
if ((ntohl(pol->magic) != ACM_MAGIC) ||
|
||||
(ntohs(pol->primary_policy_code) != acm_bin_pol.primary_policy_code) ||
|
||||
(ntohs(pol->secondary_policy_code) != acm_bin_pol.secondary_policy_code) ||
|
||||
(ntohl(pol->policyversion) != POLICY_INTERFACE_VERSION)) {
|
||||
printkd("%s: Wrong policy magics!\n", __func__);
|
||||
(ntohl(pol->policy_version) != ACM_POLICY_VERSION) ||
|
||||
(ntohl(pol->primary_policy_code) != acm_bin_pol.primary_policy_code) ||
|
||||
(ntohl(pol->secondary_policy_code) != acm_bin_pol.secondary_policy_code)) {
|
||||
printkd("%s: Wrong policy magics or versions!\n", __func__);
|
||||
goto error_free;
|
||||
}
|
||||
if (buf_size != ntohl(pol->len)) {
|
||||
@@ -79,21 +69,19 @@ acm_set_policy(void *buf, u16 buf_size, u16 policy, int isuserbuffer)
|
||||
/* get bin_policy lock and rewrite policy (release old one) */
|
||||
write_lock(&acm_bin_pol_rwlock);
|
||||
|
||||
/* 3. now get/set primary policy data */
|
||||
if (acm_primary_ops->set_binary_policy(buf + ntohs(pol->primary_buffer_offset),
|
||||
ntohs(pol->secondary_buffer_offset) -
|
||||
ntohs(pol->primary_buffer_offset))) {
|
||||
/* 3. set primary policy data */
|
||||
if (acm_primary_ops->set_binary_policy(buf + ntohl(pol->primary_buffer_offset),
|
||||
ntohl(pol->secondary_buffer_offset) -
|
||||
ntohl(pol->primary_buffer_offset))) {
|
||||
goto error_lock_free;
|
||||
}
|
||||
/* 4. now get/set secondary policy data */
|
||||
if (acm_secondary_ops->set_binary_policy(buf + ntohs(pol->secondary_buffer_offset),
|
||||
/* 4. set secondary policy data */
|
||||
if (acm_secondary_ops->set_binary_policy(buf + ntohl(pol->secondary_buffer_offset),
|
||||
ntohl(pol->len) -
|
||||
ntohs(pol->secondary_buffer_offset))) {
|
||||
ntohl(pol->secondary_buffer_offset))) {
|
||||
goto error_lock_free;
|
||||
}
|
||||
write_unlock(&acm_bin_pol_rwlock);
|
||||
out:
|
||||
printk("%s: Done .\n", __func__);
|
||||
if (policy_buffer != NULL)
|
||||
xfree(policy_buffer);
|
||||
return ACM_OK;
|
||||
@@ -121,26 +109,25 @@ acm_get_policy(void *buf, u16 buf_size)
|
||||
/* future: read policy from file and set it */
|
||||
bin_pol = (struct acm_policy_buffer *)policy_buffer;
|
||||
bin_pol->magic = htonl(ACM_MAGIC);
|
||||
bin_pol->policyversion = htonl(POLICY_INTERFACE_VERSION);
|
||||
bin_pol->primary_policy_code = htons(acm_bin_pol.primary_policy_code);
|
||||
bin_pol->secondary_policy_code = htons(acm_bin_pol.secondary_policy_code);
|
||||
bin_pol->primary_policy_code = htonl(acm_bin_pol.primary_policy_code);
|
||||
bin_pol->secondary_policy_code = htonl(acm_bin_pol.secondary_policy_code);
|
||||
|
||||
bin_pol->len = htonl(sizeof(struct acm_policy_buffer));
|
||||
bin_pol->primary_buffer_offset = htons(ntohl(bin_pol->len));
|
||||
bin_pol->secondary_buffer_offset = htons(ntohl(bin_pol->len));
|
||||
bin_pol->primary_buffer_offset = htonl(ntohl(bin_pol->len));
|
||||
bin_pol->secondary_buffer_offset = htonl(ntohl(bin_pol->len));
|
||||
|
||||
ret = acm_primary_ops->dump_binary_policy (policy_buffer + ntohs(bin_pol->primary_buffer_offset),
|
||||
buf_size - ntohs(bin_pol->primary_buffer_offset));
|
||||
ret = acm_primary_ops->dump_binary_policy (policy_buffer + ntohl(bin_pol->primary_buffer_offset),
|
||||
buf_size - ntohl(bin_pol->primary_buffer_offset));
|
||||
if (ret < 0) {
|
||||
printk("%s: ERROR creating chwallpolicy buffer.\n", __func__);
|
||||
read_unlock(&acm_bin_pol_rwlock);
|
||||
return -1;
|
||||
}
|
||||
bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
|
||||
bin_pol->secondary_buffer_offset = htons(ntohl(bin_pol->len));
|
||||
bin_pol->secondary_buffer_offset = htonl(ntohl(bin_pol->len));
|
||||
|
||||
ret = acm_secondary_ops->dump_binary_policy(policy_buffer + ntohs(bin_pol->secondary_buffer_offset),
|
||||
buf_size - ntohs(bin_pol->secondary_buffer_offset));
|
||||
ret = acm_secondary_ops->dump_binary_policy(policy_buffer + ntohl(bin_pol->secondary_buffer_offset),
|
||||
buf_size - ntohl(bin_pol->secondary_buffer_offset));
|
||||
if (ret < 0) {
|
||||
printk("%s: ERROR creating chwallpolicy buffer.\n", __func__);
|
||||
read_unlock(&acm_bin_pol_rwlock);
|
||||
@@ -178,11 +165,10 @@ acm_dump_statistics(void *buf, u16 buf_size)
|
||||
goto error_lock_free;
|
||||
|
||||
acm_stats.magic = htonl(ACM_MAGIC);
|
||||
acm_stats.policyversion = htonl(POLICY_INTERFACE_VERSION);
|
||||
acm_stats.primary_policy_code = htons(acm_bin_pol.primary_policy_code);
|
||||
acm_stats.secondary_policy_code = htons(acm_bin_pol.secondary_policy_code);
|
||||
acm_stats.primary_stats_offset = htons(sizeof(struct acm_stats_buffer));
|
||||
acm_stats.secondary_stats_offset = htons(sizeof(struct acm_stats_buffer) + len1);
|
||||
acm_stats.primary_policy_code = htonl(acm_bin_pol.primary_policy_code);
|
||||
acm_stats.secondary_policy_code = htonl(acm_bin_pol.secondary_policy_code);
|
||||
acm_stats.primary_stats_offset = htonl(sizeof(struct acm_stats_buffer));
|
||||
acm_stats.secondary_stats_offset = htonl(sizeof(struct acm_stats_buffer) + len1);
|
||||
acm_stats.len = htonl(sizeof(struct acm_stats_buffer) + len1 + len2);
|
||||
memcpy(stats_buffer, &acm_stats, sizeof(struct acm_stats_buffer));
|
||||
|
||||
|
||||
@@ -140,15 +140,15 @@ ste_dump_policy(u8 *buf, u16 buf_size) {
|
||||
struct acm_ste_policy_buffer *ste_buf = (struct acm_ste_policy_buffer *)buf;
|
||||
int ret = 0;
|
||||
|
||||
ste_buf->ste_max_types = htons(ste_bin_pol.max_types);
|
||||
ste_buf->ste_max_ssidrefs = htons(ste_bin_pol.max_ssidrefs);
|
||||
ste_buf->policy_code = htons(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
|
||||
ste_buf->ste_ssid_offset = htons(sizeof(struct acm_ste_policy_buffer));
|
||||
ret = ntohs(ste_buf->ste_ssid_offset) +
|
||||
ste_buf->ste_max_types = htonl(ste_bin_pol.max_types);
|
||||
ste_buf->ste_max_ssidrefs = htonl(ste_bin_pol.max_ssidrefs);
|
||||
ste_buf->policy_code = htonl(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
|
||||
ste_buf->ste_ssid_offset = htonl(sizeof(struct acm_ste_policy_buffer));
|
||||
ret = ntohl(ste_buf->ste_ssid_offset) +
|
||||
sizeof(domaintype_t)*ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types;
|
||||
|
||||
/* now copy buffer over */
|
||||
arrcpy(buf + ntohs(ste_buf->ste_ssid_offset),
|
||||
arrcpy(buf + ntohl(ste_buf->ste_ssid_offset),
|
||||
ste_bin_pol.ssidrefs,
|
||||
sizeof(domaintype_t),
|
||||
ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types);
|
||||
@@ -276,10 +276,16 @@ ste_set_policy(u8 *buf, u16 buf_size)
|
||||
int i;
|
||||
|
||||
/* Convert endianess of policy */
|
||||
ste_buf->policy_code = ntohs(ste_buf->policy_code);
|
||||
ste_buf->ste_max_types = ntohs(ste_buf->ste_max_types);
|
||||
ste_buf->ste_max_ssidrefs = ntohs(ste_buf->ste_max_ssidrefs);
|
||||
ste_buf->ste_ssid_offset = ntohs(ste_buf->ste_ssid_offset);
|
||||
ste_buf->policy_code = ntohl(ste_buf->policy_code);
|
||||
ste_buf->policy_version = ntohl(ste_buf->policy_version);
|
||||
ste_buf->ste_max_types = ntohl(ste_buf->ste_max_types);
|
||||
ste_buf->ste_max_ssidrefs = ntohl(ste_buf->ste_max_ssidrefs);
|
||||
ste_buf->ste_ssid_offset = ntohl(ste_buf->ste_ssid_offset);
|
||||
|
||||
/* policy type and version checks */
|
||||
if ((ste_buf->policy_code != ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) ||
|
||||
(ste_buf->policy_version != ACM_STE_VERSION))
|
||||
return -EINVAL;
|
||||
|
||||
/* 1. create and copy-in new ssidrefs buffer */
|
||||
ssidrefsbuf = xmalloc_array(u8, sizeof(domaintype_t)*ste_buf->ste_max_types*ste_buf->ste_max_ssidrefs);
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include <xen/sched.h>
|
||||
#include <xen/trace.h>
|
||||
|
||||
#if CONFIG_PAGING_LEVELS >= 4
|
||||
#if CONFIG_PAGING_LEVELS >= 3
|
||||
#include <asm/shadow_64.h>
|
||||
|
||||
extern struct shadow_ops MODE_F_HANDLER;
|
||||
@@ -233,7 +233,20 @@ void free_monitor_pagetable(struct vcpu *v)
|
||||
v->arch.monitor_vtable = 0;
|
||||
}
|
||||
|
||||
#elif CONFIG_PAGING_LEVELS == 3
|
||||
|
||||
static void alloc_monitor_pagetable(struct vcpu *v)
|
||||
{
|
||||
BUG(); /* PAE not implemented yet */
|
||||
}
|
||||
|
||||
void free_monitor_pagetable(struct vcpu *v)
|
||||
{
|
||||
BUG(); /* PAE not implemented yet */
|
||||
}
|
||||
|
||||
#elif CONFIG_PAGING_LEVELS == 2
|
||||
|
||||
static void alloc_monitor_pagetable(struct vcpu *v)
|
||||
{
|
||||
unsigned long mmfn;
|
||||
|
||||
@@ -751,7 +751,7 @@ ENTRY(hypercall_table)
|
||||
.long do_boot_vcpu
|
||||
.long do_ni_hypercall /* 25 */
|
||||
.long do_mmuext_op
|
||||
.long do_policy_op /* 27 */
|
||||
.long do_acm_op /* 27 */
|
||||
.rept NR_hypercalls-((.-hypercall_table)/4)
|
||||
.long do_ni_hypercall
|
||||
.endr
|
||||
@@ -587,7 +587,7 @@ ENTRY(hypercall_table)
|
||||
.quad do_boot_vcpu
|
||||
.quad do_set_segment_base /* 25 */
|
||||
.quad do_mmuext_op
|
||||
.quad do_policy_op
|
||||
.quad do_acm_op
|
||||
.rept NR_hypercalls-((.-hypercall_table)/4)
|
||||
.quad do_ni_hypercall
|
||||
.endr
|
||||
@@ -0,0 +1,127 @@
|
||||
/******************************************************************************
|
||||
* acm_ops.c
|
||||
*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Author:
|
||||
* 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.
|
||||
*
|
||||
* Process acm command requests from guest OS.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <xen/config.h>
|
||||
#include <xen/types.h>
|
||||
#include <xen/lib.h>
|
||||
#include <xen/mm.h>
|
||||
#include <public/acm_ops.h>
|
||||
#include <xen/sched.h>
|
||||
#include <xen/event.h>
|
||||
#include <xen/trace.h>
|
||||
#include <xen/console.h>
|
||||
#include <asm/shadow.h>
|
||||
#include <public/sched_ctl.h>
|
||||
#include <acm/acm_hooks.h>
|
||||
|
||||
#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
|
||||
|
||||
long do_acm_op(acm_op_t * u_acm_op)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
typedef enum acm_operation {
|
||||
POLICY, /* access to policy interface (early drop) */
|
||||
GETPOLICY, /* dump policy cache */
|
||||
SETPOLICY, /* set policy cache (controls security) */
|
||||
DUMPSTATS /* dump policy statistics */
|
||||
} acm_operation_t;
|
||||
|
||||
int acm_authorize_acm_ops(struct domain *d, acm_operation_t pops)
|
||||
{
|
||||
/* all policy management functions are restricted to privileged domains,
|
||||
* soon we will introduce finer-grained privileges for policy operations
|
||||
*/
|
||||
if (!IS_PRIV(d))
|
||||
{
|
||||
printk("%s: ACM management authorization denied ERROR!\n", __func__);
|
||||
return ACM_ACCESS_DENIED;
|
||||
}
|
||||
return ACM_ACCESS_PERMITTED;
|
||||
}
|
||||
|
||||
long do_acm_op(acm_op_t * u_acm_op)
|
||||
{
|
||||
long ret = 0;
|
||||
acm_op_t curop, *op = &curop;
|
||||
|
||||
/* check here policy decision for policy commands */
|
||||
/* for now allow DOM0 only, later indepedently */
|
||||
if (acm_authorize_acm_ops(current->domain, POLICY))
|
||||
return -EACCES;
|
||||
|
||||
if (copy_from_user(op, u_acm_op, sizeof(*op)))
|
||||
return -EFAULT;
|
||||
|
||||
if (op->interface_version != ACM_INTERFACE_VERSION)
|
||||
return -EACCES;
|
||||
|
||||
switch (op->cmd)
|
||||
{
|
||||
case ACM_SETPOLICY:
|
||||
{
|
||||
if (acm_authorize_acm_ops(current->domain, SETPOLICY))
|
||||
return -EACCES;
|
||||
printkd("%s: setting policy.\n", __func__);
|
||||
ret = acm_set_policy(op->u.setpolicy.pushcache,
|
||||
op->u.setpolicy.pushcache_size, 1);
|
||||
if (ret == ACM_OK)
|
||||
ret = 0;
|
||||
else
|
||||
ret = -ESRCH;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACM_GETPOLICY:
|
||||
{
|
||||
if (acm_authorize_acm_ops(current->domain, GETPOLICY))
|
||||
return -EACCES;
|
||||
printkd("%s: getting policy.\n", __func__);
|
||||
ret = acm_get_policy(op->u.getpolicy.pullcache,
|
||||
op->u.getpolicy.pullcache_size);
|
||||
if (ret == ACM_OK)
|
||||
ret = 0;
|
||||
else
|
||||
ret = -ESRCH;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACM_DUMPSTATS:
|
||||
{
|
||||
if (acm_authorize_acm_ops(current->domain, DUMPSTATS))
|
||||
return -EACCES;
|
||||
printkd("%s: dumping statistics.\n", __func__);
|
||||
ret = acm_dump_statistics(op->u.dumpstats.pullcache,
|
||||
op->u.dumpstats.pullcache_size);
|
||||
if (ret == ACM_OK)
|
||||
ret = 0;
|
||||
else
|
||||
ret = -ESRCH;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -ESRCH;
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,133 +0,0 @@
|
||||
/******************************************************************************
|
||||
* policy_ops.c
|
||||
*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Author:
|
||||
* 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.
|
||||
*
|
||||
* Process policy command requests from guest OS.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <xen/config.h>
|
||||
#include <xen/types.h>
|
||||
#include <xen/lib.h>
|
||||
#include <xen/mm.h>
|
||||
#include <public/policy_ops.h>
|
||||
#include <xen/sched.h>
|
||||
#include <xen/event.h>
|
||||
#include <xen/trace.h>
|
||||
#include <xen/console.h>
|
||||
#include <asm/shadow.h>
|
||||
#include <public/sched_ctl.h>
|
||||
#include <acm/acm_hooks.h>
|
||||
|
||||
#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
|
||||
|
||||
long do_policy_op(policy_op_t *u_policy_op)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
typedef enum policyoperation {
|
||||
POLICY, /* access to policy interface (early drop) */
|
||||
GETPOLICY, /* dump policy cache */
|
||||
SETPOLICY, /* set policy cache (controls security) */
|
||||
DUMPSTATS /* dump policy statistics */
|
||||
} policyoperation_t;
|
||||
|
||||
int
|
||||
acm_authorize_policyops(struct domain *d, policyoperation_t pops)
|
||||
{
|
||||
/* all policy management functions are restricted to privileged domains,
|
||||
* soon we will introduce finer-grained privileges for policy operations
|
||||
*/
|
||||
if (!IS_PRIV(d)) {
|
||||
printk("%s: Policy management authorization denied ERROR!\n",
|
||||
__func__);
|
||||
return ACM_ACCESS_DENIED;
|
||||
}
|
||||
return ACM_ACCESS_PERMITTED;
|
||||
}
|
||||
|
||||
long do_policy_op(policy_op_t *u_policy_op)
|
||||
{
|
||||
long ret = 0;
|
||||
policy_op_t curop, *op = &curop;
|
||||
|
||||
/* check here policy decision for policy commands */
|
||||
/* for now allow DOM0 only, later indepedently */
|
||||
if (acm_authorize_policyops(current->domain, POLICY))
|
||||
return -EACCES;
|
||||
|
||||
if ( copy_from_user(op, u_policy_op, sizeof(*op)) )
|
||||
return -EFAULT;
|
||||
|
||||
if ( op->interface_version != POLICY_INTERFACE_VERSION )
|
||||
return -EACCES;
|
||||
|
||||
switch ( op->cmd )
|
||||
{
|
||||
case POLICY_SETPOLICY:
|
||||
{
|
||||
if (acm_authorize_policyops(current->domain, SETPOLICY))
|
||||
return -EACCES;
|
||||
printkd("%s: setting policy.\n", __func__);
|
||||
ret = acm_set_policy(
|
||||
op->u.setpolicy.pushcache,
|
||||
op->u.setpolicy.pushcache_size,
|
||||
op->u.setpolicy.policy_type,
|
||||
1);
|
||||
if (ret == ACM_OK)
|
||||
ret = 0;
|
||||
else
|
||||
ret = -ESRCH;
|
||||
}
|
||||
break;
|
||||
|
||||
case POLICY_GETPOLICY:
|
||||
{
|
||||
if (acm_authorize_policyops(current->domain, GETPOLICY))
|
||||
return -EACCES;
|
||||
printkd("%s: getting policy.\n", __func__);
|
||||
ret = acm_get_policy(
|
||||
op->u.getpolicy.pullcache,
|
||||
op->u.getpolicy.pullcache_size);
|
||||
if (ret == ACM_OK)
|
||||
ret = 0;
|
||||
else
|
||||
ret = -ESRCH;
|
||||
}
|
||||
break;
|
||||
|
||||
case POLICY_DUMPSTATS:
|
||||
{
|
||||
if (acm_authorize_policyops(current->domain, DUMPSTATS))
|
||||
return -EACCES;
|
||||
printkd("%s: dumping statistics.\n", __func__);
|
||||
ret = acm_dump_statistics(
|
||||
op->u.dumpstats.pullcache,
|
||||
op->u.dumpstats.pullcache_size);
|
||||
if (ret == ACM_OK)
|
||||
ret = 0;
|
||||
else
|
||||
ret = -ESRCH;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -ESRCH;
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <xen/spinlock.h>
|
||||
#include <public/acm.h>
|
||||
#include <xen/acm_policy.h>
|
||||
#include <public/policy_ops.h>
|
||||
#include <public/acm_ops.h>
|
||||
|
||||
/* Xen-internal representation of the binary policy */
|
||||
struct acm_binary_policy {
|
||||
@@ -113,7 +113,7 @@ struct ste_ssid {
|
||||
/* protos */
|
||||
int acm_init_domain_ssid(domid_t id, ssidref_t ssidref);
|
||||
int acm_free_domain_ssid(struct acm_ssid_domain *ssid);
|
||||
int acm_set_policy(void *buf, u16 buf_size, u16 policy, int isuserbuffer);
|
||||
int acm_set_policy(void *buf, u16 buf_size, int isuserbuffer);
|
||||
int acm_get_policy(void *buf, u16 buf_size);
|
||||
int acm_dump_statistics(void *buf, u16 buf_size);
|
||||
|
||||
|
||||
+38
-23
@@ -71,6 +71,14 @@
|
||||
(X == ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) ? "CHINESE WALL AND SIMPLE TYPE ENFORCEMENT policy" : \
|
||||
"UNDEFINED policy"
|
||||
|
||||
/* the following policy versions must be increased
|
||||
* whenever the interpretation of the related
|
||||
* policy's data structure changes
|
||||
*/
|
||||
#define ACM_POLICY_VERSION 1
|
||||
#define ACM_CHWALL_VERSION 1
|
||||
#define ACM_STE_VERSION 1
|
||||
|
||||
/* defines a ssid reference used by xen */
|
||||
typedef u32 ssidref_t;
|
||||
|
||||
@@ -102,46 +110,53 @@ typedef u16 domaintype_t;
|
||||
#define ACM_MAGIC 0x0001debc
|
||||
|
||||
/* each offset in bytes from start of the struct they
|
||||
* the are part of */
|
||||
* are part of */
|
||||
|
||||
/* each buffer consists of all policy information for
|
||||
* the respective policy given in the policy code
|
||||
*
|
||||
* acm_policy_buffer, acm_chwall_policy_buffer,
|
||||
* and acm_ste_policy_buffer need to stay 32-bit aligned
|
||||
* because we create binary policies also with external
|
||||
* tools that assume packed representations (e.g. the java tool)
|
||||
*/
|
||||
struct acm_policy_buffer {
|
||||
u32 policy_version; /* ACM_POLICY_VERSION */
|
||||
u32 magic;
|
||||
u32 policyversion;
|
||||
u32 len;
|
||||
u16 primary_policy_code;
|
||||
u16 primary_buffer_offset;
|
||||
u16 secondary_policy_code;
|
||||
u16 secondary_buffer_offset;
|
||||
u32 primary_policy_code;
|
||||
u32 primary_buffer_offset;
|
||||
u32 secondary_policy_code;
|
||||
u32 secondary_buffer_offset;
|
||||
};
|
||||
|
||||
struct acm_chwall_policy_buffer {
|
||||
u16 policy_code;
|
||||
u16 chwall_max_types;
|
||||
u16 chwall_max_ssidrefs;
|
||||
u16 chwall_max_conflictsets;
|
||||
u16 chwall_ssid_offset;
|
||||
u16 chwall_conflict_sets_offset;
|
||||
u16 chwall_running_types_offset;
|
||||
u16 chwall_conflict_aggregate_offset;
|
||||
u32 policy_version; /* ACM_CHWALL_VERSION */
|
||||
u32 policy_code;
|
||||
u32 chwall_max_types;
|
||||
u32 chwall_max_ssidrefs;
|
||||
u32 chwall_max_conflictsets;
|
||||
u32 chwall_ssid_offset;
|
||||
u32 chwall_conflict_sets_offset;
|
||||
u32 chwall_running_types_offset;
|
||||
u32 chwall_conflict_aggregate_offset;
|
||||
};
|
||||
|
||||
struct acm_ste_policy_buffer {
|
||||
u16 policy_code;
|
||||
u16 ste_max_types;
|
||||
u16 ste_max_ssidrefs;
|
||||
u16 ste_ssid_offset;
|
||||
u32 policy_version; /* ACM_STE_VERSION */
|
||||
u32 policy_code;
|
||||
u32 ste_max_types;
|
||||
u32 ste_max_ssidrefs;
|
||||
u32 ste_ssid_offset;
|
||||
};
|
||||
|
||||
struct acm_stats_buffer {
|
||||
u32 magic;
|
||||
u32 policyversion;
|
||||
u32 len;
|
||||
u16 primary_policy_code;
|
||||
u16 primary_stats_offset;
|
||||
u16 secondary_policy_code;
|
||||
u16 secondary_stats_offset;
|
||||
u32 primary_policy_code;
|
||||
u32 primary_stats_offset;
|
||||
u32 secondary_policy_code;
|
||||
u32 secondary_stats_offset;
|
||||
};
|
||||
|
||||
struct acm_ste_stats_buffer {
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/******************************************************************************
|
||||
* acm_ops.h
|
||||
*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Author:
|
||||
* 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.
|
||||
*
|
||||
* Process acm policy command requests from guest OS.
|
||||
* access checked by policy; not restricted to DOM0
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __XEN_PUBLIC_ACM_OPS_H__
|
||||
#define __XEN_PUBLIC_ACM_OPS_H__
|
||||
|
||||
#include "xen.h"
|
||||
#include "sched_ctl.h"
|
||||
|
||||
/*
|
||||
* Make sure you increment the interface version whenever you modify this file!
|
||||
* This makes sure that old versions of acm tools will stop working in a
|
||||
* well-defined way (rather than crashing the machine, for instance).
|
||||
*/
|
||||
#define ACM_INTERFACE_VERSION 0xAAAA0003
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
#define ACM_SETPOLICY 4
|
||||
typedef struct acm_setpolicy {
|
||||
/* OUT variables */
|
||||
void *pushcache;
|
||||
u16 pushcache_size;
|
||||
} acm_setpolicy_t;
|
||||
|
||||
|
||||
#define ACM_GETPOLICY 5
|
||||
typedef struct acm_getpolicy {
|
||||
/* OUT variables */
|
||||
void *pullcache;
|
||||
u16 pullcache_size;
|
||||
} acm_getpolicy_t;
|
||||
|
||||
#define ACM_DUMPSTATS 6
|
||||
typedef struct acm_dumpstats {
|
||||
void *pullcache;
|
||||
u16 pullcache_size;
|
||||
} acm_dumpstats_t;
|
||||
|
||||
|
||||
typedef struct acm_op {
|
||||
u32 cmd;
|
||||
u32 interface_version; /* ACM_INTERFACE_VERSION */
|
||||
union {
|
||||
acm_setpolicy_t setpolicy;
|
||||
acm_getpolicy_t getpolicy;
|
||||
acm_dumpstats_t dumpstats;
|
||||
} u;
|
||||
} acm_op_t;
|
||||
|
||||
#endif /* __XEN_PUBLIC_ACM_OPS_H__ */
|
||||
@@ -1,70 +0,0 @@
|
||||
/******************************************************************************
|
||||
* policy_ops.h
|
||||
*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Author:
|
||||
* 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.
|
||||
*
|
||||
* Process policy command requests from guest OS.
|
||||
* access checked by policy; not restricted to DOM0
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __XEN_PUBLIC_POLICY_OPS_H__
|
||||
#define __XEN_PUBLIC_POLICY_OPS_H__
|
||||
|
||||
#include "xen.h"
|
||||
#include "sched_ctl.h"
|
||||
|
||||
/*
|
||||
* Make sure you increment the interface version whenever you modify this file!
|
||||
* This makes sure that old versions of policy tools will stop working in a
|
||||
* well-defined way (rather than crashing the machine, for instance).
|
||||
*/
|
||||
#define POLICY_INTERFACE_VERSION 0xAAAA0003
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
#define POLICY_SETPOLICY 4
|
||||
typedef struct policy_setpolicy {
|
||||
/* IN variables. */
|
||||
u16 policy_type;
|
||||
/* OUT variables */
|
||||
void *pushcache;
|
||||
u16 pushcache_size;
|
||||
} policy_setpolicy_t;
|
||||
|
||||
|
||||
#define POLICY_GETPOLICY 5
|
||||
typedef struct policy_getpolicy {
|
||||
/* IN variables. */
|
||||
u16 policy_type;
|
||||
/* OUT variables */
|
||||
void *pullcache;
|
||||
u16 pullcache_size;
|
||||
} policy_getpolicy_t;
|
||||
|
||||
#define POLICY_DUMPSTATS 6
|
||||
typedef struct policy_dumpstats {
|
||||
void *pullcache;
|
||||
u16 pullcache_size;
|
||||
} policy_dumpstats_t;
|
||||
|
||||
|
||||
typedef struct policy_op {
|
||||
u32 cmd;
|
||||
u32 interface_version; /* POLICY_INTERFACE_VERSION */
|
||||
union {
|
||||
policy_setpolicy_t setpolicy;
|
||||
policy_getpolicy_t getpolicy;
|
||||
policy_dumpstats_t dumpstats;
|
||||
} u;
|
||||
} policy_op_t;
|
||||
|
||||
#endif /* __XEN_PUBLIC_POLICY_OPS_H__ */
|
||||
@@ -58,7 +58,7 @@
|
||||
#define __HYPERVISOR_boot_vcpu 24
|
||||
#define __HYPERVISOR_set_segment_base 25 /* x86/64 only */
|
||||
#define __HYPERVISOR_mmuext_op 26
|
||||
#define __HYPERVISOR_policy_op 27
|
||||
#define __HYPERVISOR_acm_op 27
|
||||
|
||||
/*
|
||||
* VIRTUAL INTERRUPTS
|
||||
|
||||