Merging with xen-unstable

This commit is contained in:
djm@kirby.fc.hp.com committed 2005-08-02 10:20:46 -07:00
commit 31dfa31bc0
46 files changed
+2617 -1588

No files matched your search

+4 -2
View File
@@ -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
+58 -21
View File
@@ -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");
-391
View File
@@ -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;
}
+3 -3
View File
@@ -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
View File
@@ -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
+2
View File
@@ -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
+48
View File
@@ -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)
+328
View File
@@ -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);
}
+26
View File
@@ -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
+93
View File
@@ -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;
}
+251
View File
@@ -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;
}
+47
View File
@@ -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
+236
View File
@@ -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;
}
+39
View File
@@ -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;
}
+42
View File
@@ -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 . )
+172 -201
View File
@@ -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;
}
+57
View File
@@ -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>
-552
View File
@@ -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;
}
+1 -1
View File
@@ -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',
+1 -1
View File
@@ -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())
+20 -13
View File
@@ -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
View File
@@ -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:
+5 -2
View File
@@ -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)
+16 -5
View File
@@ -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
+648
View File
@@ -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;
}
+30 -24
View File
@@ -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);
-1
View File
@@ -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
View File
@@ -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));
+16 -10
View File
@@ -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);
+14 -1
View File
@@ -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;
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+127
View File
@@ -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
-133
View File
@@ -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
+2 -2
View File
@@ -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
View File
@@ -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 {
+66
View File
@@ -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__ */
-70
View File
@@ -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__ */
+1 -1
View File
@@ -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
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.