mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
Merged.
This commit is contained in:
commit
53dcf75ccb
26 files changed
+1097
-700
No files matched your search
@@ -12,6 +12,8 @@
|
||||
*/
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/list.h>
|
||||
#include <asm-xen/balloon.h>
|
||||
#include <asm/hypervisor.h>
|
||||
#include "common.h"
|
||||
@@ -21,26 +23,26 @@
|
||||
* pulled from a communication ring are quite likely to end up being part of
|
||||
* the same scatter/gather request at the disc.
|
||||
*
|
||||
* ** TRY INCREASING 'MAX_PENDING_REQS' IF WRITE SPEEDS SEEM TOO LOW **
|
||||
* ** TRY INCREASING 'blkif_reqs' IF WRITE SPEEDS SEEM TOO LOW **
|
||||
*
|
||||
* This will increase the chances of being able to write whole tracks.
|
||||
* 64 should be enough to keep us competitive with Linux.
|
||||
*/
|
||||
#define MAX_PENDING_REQS 64
|
||||
#define BATCH_PER_DOMAIN 16
|
||||
static int blkif_reqs = 64;
|
||||
static int mmap_pages;
|
||||
|
||||
static unsigned long mmap_vstart;
|
||||
#define MMAP_PAGES \
|
||||
(MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
|
||||
#ifdef __ia64__
|
||||
static void *pending_vaddrs[MMAP_PAGES];
|
||||
#define MMAP_VADDR(_idx, _i) \
|
||||
(unsigned long)(pending_vaddrs[((_idx) * BLKIF_MAX_SEGMENTS_PER_REQUEST) + (_i)])
|
||||
#else
|
||||
#define MMAP_VADDR(_req,_seg) \
|
||||
(mmap_vstart + \
|
||||
((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) + \
|
||||
((_seg) * PAGE_SIZE))
|
||||
#endif
|
||||
static int __init set_blkif_reqs(char *str)
|
||||
{
|
||||
get_option(&str, &blkif_reqs);
|
||||
return 1;
|
||||
}
|
||||
__setup("blkif_reqs=", set_blkif_reqs);
|
||||
|
||||
/* Run-time switchable: /sys/module/blkback/parameters/ */
|
||||
static unsigned int log_stats = 0;
|
||||
static unsigned int debug_lvl = 0;
|
||||
module_param(log_stats, int, 0644);
|
||||
module_param(debug_lvl, int, 0644);
|
||||
|
||||
/*
|
||||
* Each outstanding request that we've passed to the lower device layers has a
|
||||
@@ -55,43 +57,33 @@ typedef struct {
|
||||
atomic_t pendcnt;
|
||||
unsigned short operation;
|
||||
int status;
|
||||
struct list_head free_list;
|
||||
} pending_req_t;
|
||||
|
||||
/*
|
||||
* We can't allocate pending_req's in order, since they may complete out of
|
||||
* order. We therefore maintain an allocation ring. This ring also indicates
|
||||
* when enough work has been passed down -- at that point the allocation ring
|
||||
* will be empty.
|
||||
*/
|
||||
static pending_req_t pending_reqs[MAX_PENDING_REQS];
|
||||
static unsigned char pending_ring[MAX_PENDING_REQS];
|
||||
static spinlock_t pend_prod_lock = SPIN_LOCK_UNLOCKED;
|
||||
/* NB. We use a different index type to differentiate from shared blk rings. */
|
||||
typedef unsigned int PEND_RING_IDX;
|
||||
#define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1))
|
||||
static PEND_RING_IDX pending_prod, pending_cons;
|
||||
#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons)
|
||||
static pending_req_t *pending_reqs;
|
||||
static struct list_head pending_free;
|
||||
static spinlock_t pending_free_lock = SPIN_LOCK_UNLOCKED;
|
||||
static DECLARE_WAIT_QUEUE_HEAD(pending_free_wq);
|
||||
|
||||
static request_queue_t *plugged_queue;
|
||||
static inline void flush_plugged_queue(void)
|
||||
#define BLKBACK_INVALID_HANDLE (~0)
|
||||
|
||||
static unsigned long mmap_vstart;
|
||||
static unsigned long *pending_vaddrs;
|
||||
static grant_handle_t *pending_grant_handles;
|
||||
|
||||
static inline int vaddr_pagenr(pending_req_t *req, int seg)
|
||||
{
|
||||
request_queue_t *q = plugged_queue;
|
||||
if (q != NULL) {
|
||||
if ( q->unplug_fn != NULL )
|
||||
q->unplug_fn(q);
|
||||
blk_put_queue(q);
|
||||
plugged_queue = NULL;
|
||||
}
|
||||
return (req - pending_reqs) * BLKIF_MAX_SEGMENTS_PER_REQUEST + seg;
|
||||
}
|
||||
|
||||
/* When using grant tables to map a frame for device access then the
|
||||
* handle returned must be used to unmap the frame. This is needed to
|
||||
* drop the ref count on the frame.
|
||||
*/
|
||||
static grant_handle_t pending_grant_handles[MMAP_PAGES];
|
||||
#define pending_handle(_idx, _i) \
|
||||
(pending_grant_handles[((_idx) * BLKIF_MAX_SEGMENTS_PER_REQUEST) + (_i)])
|
||||
#define BLKBACK_INVALID_HANDLE (~0)
|
||||
static inline unsigned long vaddr(pending_req_t *req, int seg)
|
||||
{
|
||||
return pending_vaddrs[vaddr_pagenr(req, seg)];
|
||||
}
|
||||
|
||||
#define pending_handle(_req, _seg) \
|
||||
(pending_grant_handles[vaddr_pagenr(_req, _seg)])
|
||||
|
||||
|
||||
#ifdef CONFIG_XEN_BLKDEV_TAP_BE
|
||||
/*
|
||||
@@ -105,26 +97,79 @@ static grant_handle_t pending_grant_handles[MMAP_PAGES];
|
||||
static inline domid_t ID_TO_DOM(unsigned long id) { return (id >> 16); }
|
||||
#endif
|
||||
|
||||
static int do_block_io_op(blkif_t *blkif, int max_to_do);
|
||||
static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req);
|
||||
static int do_block_io_op(blkif_t *blkif);
|
||||
static void dispatch_rw_block_io(blkif_t *blkif,
|
||||
blkif_request_t *req,
|
||||
pending_req_t *pending_req);
|
||||
static void make_response(blkif_t *blkif, unsigned long id,
|
||||
unsigned short op, int st);
|
||||
|
||||
static void fast_flush_area(int idx, int nr_pages)
|
||||
/******************************************************************
|
||||
* misc small helpers
|
||||
*/
|
||||
static pending_req_t* alloc_req(void)
|
||||
{
|
||||
pending_req_t *req = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&pending_free_lock, flags);
|
||||
if (!list_empty(&pending_free)) {
|
||||
req = list_entry(pending_free.next, pending_req_t, free_list);
|
||||
list_del(&req->free_list);
|
||||
}
|
||||
spin_unlock_irqrestore(&pending_free_lock, flags);
|
||||
return req;
|
||||
}
|
||||
|
||||
static void free_req(pending_req_t *req)
|
||||
{
|
||||
unsigned long flags;
|
||||
int was_empty;
|
||||
|
||||
spin_lock_irqsave(&pending_free_lock, flags);
|
||||
was_empty = list_empty(&pending_free);
|
||||
list_add(&req->free_list, &pending_free);
|
||||
spin_unlock_irqrestore(&pending_free_lock, flags);
|
||||
if (was_empty)
|
||||
wake_up(&pending_free_wq);
|
||||
}
|
||||
|
||||
static void unplug_queue(blkif_t *blkif)
|
||||
{
|
||||
if (blkif->plug == NULL)
|
||||
return;
|
||||
if (blkif->plug->unplug_fn)
|
||||
blkif->plug->unplug_fn(blkif->plug);
|
||||
blk_put_queue(blkif->plug);
|
||||
blkif->plug = NULL;
|
||||
}
|
||||
|
||||
static void plug_queue(blkif_t *blkif, struct bio *bio)
|
||||
{
|
||||
request_queue_t *q = bdev_get_queue(bio->bi_bdev);
|
||||
|
||||
if (q == blkif->plug)
|
||||
return;
|
||||
unplug_queue(blkif);
|
||||
blk_get_queue(q);
|
||||
blkif->plug = q;
|
||||
}
|
||||
|
||||
static void fast_flush_area(pending_req_t *req)
|
||||
{
|
||||
struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
|
||||
unsigned int i, invcount = 0;
|
||||
grant_handle_t handle;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < nr_pages; i++) {
|
||||
handle = pending_handle(idx, i);
|
||||
for (i = 0; i < req->nr_pages; i++) {
|
||||
handle = pending_handle(req, i);
|
||||
if (handle == BLKBACK_INVALID_HANDLE)
|
||||
continue;
|
||||
unmap[invcount].host_addr = MMAP_VADDR(idx, i);
|
||||
unmap[invcount].host_addr = vaddr(req, i);
|
||||
unmap[invcount].dev_bus_addr = 0;
|
||||
unmap[invcount].handle = handle;
|
||||
pending_handle(idx, i) = BLKBACK_INVALID_HANDLE;
|
||||
pending_handle(req, i) = BLKBACK_INVALID_HANDLE;
|
||||
invcount++;
|
||||
}
|
||||
|
||||
@@ -133,118 +178,90 @@ static void fast_flush_area(int idx, int nr_pages)
|
||||
BUG_ON(ret);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* BLOCK-DEVICE SCHEDULER LIST MAINTENANCE
|
||||
*/
|
||||
|
||||
static struct list_head blkio_schedule_list;
|
||||
static spinlock_t blkio_schedule_list_lock;
|
||||
|
||||
static int __on_blkdev_list(blkif_t *blkif)
|
||||
{
|
||||
return blkif->blkdev_list.next != NULL;
|
||||
}
|
||||
|
||||
static void remove_from_blkdev_list(blkif_t *blkif)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (!__on_blkdev_list(blkif))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&blkio_schedule_list_lock, flags);
|
||||
if (__on_blkdev_list(blkif)) {
|
||||
list_del(&blkif->blkdev_list);
|
||||
blkif->blkdev_list.next = NULL;
|
||||
blkif_put(blkif);
|
||||
}
|
||||
spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
|
||||
}
|
||||
|
||||
static void add_to_blkdev_list_tail(blkif_t *blkif)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (__on_blkdev_list(blkif))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&blkio_schedule_list_lock, flags);
|
||||
if (!__on_blkdev_list(blkif) && (blkif->status == CONNECTED)) {
|
||||
list_add_tail(&blkif->blkdev_list, &blkio_schedule_list);
|
||||
blkif_get(blkif);
|
||||
}
|
||||
spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* SCHEDULER FUNCTIONS
|
||||
*/
|
||||
|
||||
static DECLARE_WAIT_QUEUE_HEAD(blkio_schedule_wait);
|
||||
|
||||
static int blkio_schedule(void *arg)
|
||||
static void print_stats(blkif_t *blkif)
|
||||
{
|
||||
DECLARE_WAITQUEUE(wq, current);
|
||||
printk(KERN_DEBUG "%s: oo %3d | rd %4d | wr %4d\n",
|
||||
current->comm, blkif->st_oo_req,
|
||||
blkif->st_rd_req, blkif->st_wr_req);
|
||||
blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000);
|
||||
blkif->st_rd_req = 0;
|
||||
blkif->st_wr_req = 0;
|
||||
blkif->st_oo_req = 0;
|
||||
}
|
||||
|
||||
blkif_t *blkif;
|
||||
struct list_head *ent;
|
||||
|
||||
daemonize("xenblkd");
|
||||
int blkif_schedule(void *arg)
|
||||
{
|
||||
blkif_t *blkif = arg;
|
||||
|
||||
blkif_get(blkif);
|
||||
if (debug_lvl)
|
||||
printk(KERN_DEBUG "%s: started\n", current->comm);
|
||||
for (;;) {
|
||||
/* Wait for work to do. */
|
||||
add_wait_queue(&blkio_schedule_wait, &wq);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
if ( (NR_PENDING_REQS == MAX_PENDING_REQS) ||
|
||||
list_empty(&blkio_schedule_list) )
|
||||
schedule();
|
||||
__set_current_state(TASK_RUNNING);
|
||||
remove_wait_queue(&blkio_schedule_wait, &wq);
|
||||
|
||||
/* Queue up a batch of requests. */
|
||||
while ((NR_PENDING_REQS < MAX_PENDING_REQS) &&
|
||||
!list_empty(&blkio_schedule_list)) {
|
||||
ent = blkio_schedule_list.next;
|
||||
blkif = list_entry(ent, blkif_t, blkdev_list);
|
||||
blkif_get(blkif);
|
||||
remove_from_blkdev_list(blkif);
|
||||
if (do_block_io_op(blkif, BATCH_PER_DOMAIN))
|
||||
add_to_blkdev_list_tail(blkif);
|
||||
blkif_put(blkif);
|
||||
if (kthread_should_stop()) {
|
||||
/* asked to quit? */
|
||||
if (!atomic_read(&blkif->io_pending))
|
||||
break;
|
||||
if (debug_lvl)
|
||||
printk(KERN_DEBUG "%s: I/O pending, "
|
||||
"delaying exit\n", current->comm);
|
||||
}
|
||||
|
||||
/* Push the batch through to disc. */
|
||||
flush_plugged_queue();
|
||||
if (!atomic_read(&blkif->io_pending)) {
|
||||
/* Wait for work to do. */
|
||||
wait_event_interruptible(
|
||||
blkif->wq,
|
||||
(atomic_read(&blkif->io_pending) ||
|
||||
kthread_should_stop()));
|
||||
} else if (list_empty(&pending_free)) {
|
||||
/* Wait for pending_req becoming available. */
|
||||
wait_event_interruptible(
|
||||
pending_free_wq,
|
||||
!list_empty(&pending_free));
|
||||
}
|
||||
|
||||
if (blkif->status != CONNECTED) {
|
||||
/* make sure we are connected */
|
||||
if (debug_lvl)
|
||||
printk(KERN_DEBUG "%s: not connected "
|
||||
"(%d pending)\n",
|
||||
current->comm,
|
||||
atomic_read(&blkif->io_pending));
|
||||
wait_event_interruptible(
|
||||
blkif->wq,
|
||||
(blkif->status == CONNECTED ||
|
||||
kthread_should_stop()));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Schedule I/O */
|
||||
atomic_set(&blkif->io_pending, 0);
|
||||
if (do_block_io_op(blkif))
|
||||
atomic_inc(&blkif->io_pending);
|
||||
unplug_queue(blkif);
|
||||
|
||||
if (log_stats && time_after(jiffies, blkif->st_print))
|
||||
print_stats(blkif);
|
||||
}
|
||||
|
||||
if (log_stats)
|
||||
print_stats(blkif);
|
||||
if (debug_lvl)
|
||||
printk(KERN_DEBUG "%s: exiting\n", current->comm);
|
||||
blkif->xenblkd = NULL;
|
||||
blkif_put(blkif);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void maybe_trigger_blkio_schedule(void)
|
||||
{
|
||||
/*
|
||||
* Needed so that two processes, which together make the following
|
||||
* predicate true, don't both read stale values and evaluate the
|
||||
* predicate incorrectly. Incredibly unlikely to stall the scheduler
|
||||
* on x86, but...
|
||||
*/
|
||||
smp_mb();
|
||||
|
||||
if ((NR_PENDING_REQS < (MAX_PENDING_REQS/2)) &&
|
||||
!list_empty(&blkio_schedule_list))
|
||||
wake_up(&blkio_schedule_wait);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* COMPLETION CALLBACK -- Called as bh->b_end_io()
|
||||
*/
|
||||
|
||||
static void __end_block_io_op(pending_req_t *pending_req, int uptodate)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
/* An error fails the entire request. */
|
||||
if (!uptodate) {
|
||||
DPRINTK("Buffer not up-to-date at end of operation\n");
|
||||
@@ -252,15 +269,11 @@ static void __end_block_io_op(pending_req_t *pending_req, int uptodate)
|
||||
}
|
||||
|
||||
if (atomic_dec_and_test(&pending_req->pendcnt)) {
|
||||
int pending_idx = pending_req - pending_reqs;
|
||||
fast_flush_area(pending_idx, pending_req->nr_pages);
|
||||
fast_flush_area(pending_req);
|
||||
make_response(pending_req->blkif, pending_req->id,
|
||||
pending_req->operation, pending_req->status);
|
||||
blkif_put(pending_req->blkif);
|
||||
spin_lock_irqsave(&pend_prod_lock, flags);
|
||||
pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
|
||||
spin_unlock_irqrestore(&pend_prod_lock, flags);
|
||||
maybe_trigger_blkio_schedule();
|
||||
free_req(pending_req);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,8 +294,9 @@ static int end_block_io_op(struct bio *bio, unsigned int done, int error)
|
||||
irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
blkif_t *blkif = dev_id;
|
||||
add_to_blkdev_list_tail(blkif);
|
||||
maybe_trigger_blkio_schedule();
|
||||
|
||||
atomic_inc(&blkif->io_pending);
|
||||
wake_up(&blkif->wq);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -292,10 +306,11 @@ irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs)
|
||||
* DOWNWARD CALLS -- These interface with the block-device layer proper.
|
||||
*/
|
||||
|
||||
static int do_block_io_op(blkif_t *blkif, int max_to_do)
|
||||
static int do_block_io_op(blkif_t *blkif)
|
||||
{
|
||||
blkif_back_ring_t *blk_ring = &blkif->blk_ring;
|
||||
blkif_request_t *req;
|
||||
pending_req_t *pending_req;
|
||||
RING_IDX rc, rp;
|
||||
int more_to_do = 0;
|
||||
|
||||
@@ -304,8 +319,10 @@ static int do_block_io_op(blkif_t *blkif, int max_to_do)
|
||||
rmb(); /* Ensure we see queued requests up to 'rp'. */
|
||||
|
||||
while ((rc != rp) && !RING_REQUEST_CONS_OVERFLOW(blk_ring, rc)) {
|
||||
if ((max_to_do-- == 0) ||
|
||||
(NR_PENDING_REQS == MAX_PENDING_REQS)) {
|
||||
|
||||
pending_req = alloc_req();
|
||||
if (NULL == pending_req) {
|
||||
blkif->st_oo_req++;
|
||||
more_to_do = 1;
|
||||
break;
|
||||
}
|
||||
@@ -315,28 +332,31 @@ static int do_block_io_op(blkif_t *blkif, int max_to_do)
|
||||
|
||||
switch (req->operation) {
|
||||
case BLKIF_OP_READ:
|
||||
case BLKIF_OP_WRITE:
|
||||
dispatch_rw_block_io(blkif, req);
|
||||
blkif->st_rd_req++;
|
||||
dispatch_rw_block_io(blkif, req, pending_req);
|
||||
break;
|
||||
case BLKIF_OP_WRITE:
|
||||
blkif->st_wr_req++;
|
||||
dispatch_rw_block_io(blkif, req, pending_req);
|
||||
break;
|
||||
|
||||
default:
|
||||
DPRINTK("error: unknown block io operation [%d]\n",
|
||||
req->operation);
|
||||
make_response(blkif, req->id, req->operation,
|
||||
BLKIF_RSP_ERROR);
|
||||
free_req(pending_req);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return more_to_do;
|
||||
}
|
||||
|
||||
static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
|
||||
static void dispatch_rw_block_io(blkif_t *blkif,
|
||||
blkif_request_t *req,
|
||||
pending_req_t *pending_req)
|
||||
{
|
||||
extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]);
|
||||
int operation = (req->operation == BLKIF_OP_WRITE) ? WRITE : READ;
|
||||
int i, pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
|
||||
pending_req_t *pending_req;
|
||||
struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST];
|
||||
struct phys_req preq;
|
||||
struct {
|
||||
@@ -344,32 +364,36 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
|
||||
} seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
|
||||
unsigned int nseg;
|
||||
struct bio *bio = NULL, *biolist[BLKIF_MAX_SEGMENTS_PER_REQUEST];
|
||||
int nbio = 0;
|
||||
request_queue_t *q;
|
||||
int ret, errors = 0;
|
||||
int ret, i, nbio = 0;
|
||||
|
||||
/* Check that number of segments is sane. */
|
||||
nseg = req->nr_segments;
|
||||
if (unlikely(nseg == 0) ||
|
||||
unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) {
|
||||
DPRINTK("Bad number of segments in request (%d)\n", nseg);
|
||||
goto bad_descriptor;
|
||||
goto fail_response;
|
||||
}
|
||||
|
||||
preq.dev = req->handle;
|
||||
preq.sector_number = req->sector_number;
|
||||
preq.nr_sects = 0;
|
||||
|
||||
pending_req->blkif = blkif;
|
||||
pending_req->id = req->id;
|
||||
pending_req->operation = operation;
|
||||
pending_req->status = BLKIF_RSP_OKAY;
|
||||
pending_req->nr_pages = nseg;
|
||||
|
||||
for (i = 0; i < nseg; i++) {
|
||||
seg[i].nsec = req->seg[i].last_sect -
|
||||
req->seg[i].first_sect + 1;
|
||||
|
||||
if ((req->seg[i].last_sect >= (PAGE_SIZE >> 9)) ||
|
||||
(seg[i].nsec <= 0))
|
||||
goto bad_descriptor;
|
||||
goto fail_response;
|
||||
preq.nr_sects += seg[i].nsec;
|
||||
|
||||
map[i].host_addr = MMAP_VADDR(pending_idx, i);
|
||||
map[i].host_addr = vaddr(pending_req, i);
|
||||
map[i].dom = blkif->domid;
|
||||
map[i].ref = req->seg[i].gref;
|
||||
map[i].flags = GNTMAP_host_map;
|
||||
@@ -381,26 +405,22 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
|
||||
BUG_ON(ret);
|
||||
|
||||
for (i = 0; i < nseg; i++) {
|
||||
if (likely(map[i].status == 0)) {
|
||||
pending_handle(pending_idx, i) = map[i].handle;
|
||||
#ifdef __ia64__
|
||||
MMAP_VADDR(pending_idx,i) = gnttab_map_vaddr(map[i]);
|
||||
#else
|
||||
set_phys_to_machine(__pa(MMAP_VADDR(
|
||||
pending_idx, i)) >> PAGE_SHIFT,
|
||||
FOREIGN_FRAME(map[i].dev_bus_addr>>PAGE_SHIFT));
|
||||
#endif
|
||||
seg[i].buf = map[i].dev_bus_addr |
|
||||
(req->seg[i].first_sect << 9);
|
||||
} else {
|
||||
errors++;
|
||||
if (unlikely(map[i].status != 0)) {
|
||||
DPRINTK("invalid buffer -- could not remap it\n");
|
||||
goto fail_flush;
|
||||
}
|
||||
}
|
||||
|
||||
if (errors) {
|
||||
DPRINTK("invalid buffer -- could not remap it\n");
|
||||
fast_flush_area(pending_idx, nseg);
|
||||
goto bad_descriptor;
|
||||
pending_handle(pending_req, i) = map[i].handle;
|
||||
#ifdef __ia64__
|
||||
pending_vaddrs[vaddr_pagenr(pending_req, i)] =
|
||||
= gnttab_map_vaddr(map[i]);
|
||||
#else
|
||||
set_phys_to_machine(__pa(vaddr(
|
||||
pending_req, i)) >> PAGE_SHIFT,
|
||||
FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT));
|
||||
#endif
|
||||
seg[i].buf = map[i].dev_bus_addr |
|
||||
(req->seg[i].first_sect << 9);
|
||||
}
|
||||
|
||||
if (vbd_translate(&preq, blkif, operation) != 0) {
|
||||
@@ -408,37 +428,25 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
|
||||
operation == READ ? "read" : "write",
|
||||
preq.sector_number,
|
||||
preq.sector_number + preq.nr_sects, preq.dev);
|
||||
goto bad_descriptor;
|
||||
goto fail_flush;
|
||||
}
|
||||
|
||||
pending_req = &pending_reqs[pending_idx];
|
||||
pending_req->blkif = blkif;
|
||||
pending_req->id = req->id;
|
||||
pending_req->operation = operation;
|
||||
pending_req->status = BLKIF_RSP_OKAY;
|
||||
pending_req->nr_pages = nseg;
|
||||
|
||||
for (i = 0; i < nseg; i++) {
|
||||
if (((int)preq.sector_number|(int)seg[i].nsec) &
|
||||
((bdev_hardsect_size(preq.bdev) >> 9) - 1)) {
|
||||
DPRINTK("Misaligned I/O request from domain %d",
|
||||
blkif->domid);
|
||||
goto cleanup_and_fail;
|
||||
goto fail_put_bio;
|
||||
}
|
||||
|
||||
while ((bio == NULL) ||
|
||||
(bio_add_page(bio,
|
||||
virt_to_page(MMAP_VADDR(pending_idx, i)),
|
||||
virt_to_page(vaddr(pending_req, i)),
|
||||
seg[i].nsec << 9,
|
||||
seg[i].buf & ~PAGE_MASK) == 0)) {
|
||||
bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, nseg-i);
|
||||
if (unlikely(bio == NULL)) {
|
||||
cleanup_and_fail:
|
||||
for (i = 0; i < (nbio-1); i++)
|
||||
bio_put(biolist[i]);
|
||||
fast_flush_area(pending_idx, nseg);
|
||||
goto bad_descriptor;
|
||||
}
|
||||
if (unlikely(bio == NULL))
|
||||
goto fail_put_bio;
|
||||
|
||||
bio->bi_bdev = preq.bdev;
|
||||
bio->bi_private = pending_req;
|
||||
@@ -449,14 +457,8 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
|
||||
preq.sector_number += seg[i].nsec;
|
||||
}
|
||||
|
||||
if ((q = bdev_get_queue(bio->bi_bdev)) != plugged_queue) {
|
||||
flush_plugged_queue();
|
||||
blk_get_queue(q);
|
||||
plugged_queue = q;
|
||||
}
|
||||
|
||||
plug_queue(blkif, bio);
|
||||
atomic_set(&pending_req->pendcnt, nbio);
|
||||
pending_cons++;
|
||||
blkif_get(blkif);
|
||||
|
||||
for (i = 0; i < nbio; i++)
|
||||
@@ -464,8 +466,14 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
|
||||
|
||||
return;
|
||||
|
||||
bad_descriptor:
|
||||
fail_put_bio:
|
||||
for (i = 0; i < (nbio-1); i++)
|
||||
bio_put(biolist[i]);
|
||||
fail_flush:
|
||||
fast_flush_area(pending_req);
|
||||
fail_response:
|
||||
make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
|
||||
free_req(pending_req);
|
||||
}
|
||||
|
||||
|
||||
@@ -481,6 +489,7 @@ static void make_response(blkif_t *blkif, unsigned long id,
|
||||
blkif_response_t *resp;
|
||||
unsigned long flags;
|
||||
blkif_back_ring_t *blk_ring = &blkif->blk_ring;
|
||||
int more_to_do = 0;
|
||||
int notify;
|
||||
|
||||
spin_lock_irqsave(&blkif->blk_ring_lock, flags);
|
||||
@@ -499,76 +508,69 @@ static void make_response(blkif_t *blkif, unsigned long id,
|
||||
* notifications if requests are already in flight (lower
|
||||
* overheads and promotes batching).
|
||||
*/
|
||||
int more_to_do;
|
||||
RING_FINAL_CHECK_FOR_REQUESTS(blk_ring, more_to_do);
|
||||
if (more_to_do) {
|
||||
add_to_blkdev_list_tail(blkif);
|
||||
maybe_trigger_blkio_schedule();
|
||||
}
|
||||
}
|
||||
else if (!__on_blkdev_list(blkif)
|
||||
&& RING_HAS_UNCONSUMED_REQUESTS(blk_ring)) {
|
||||
/* Keep pulling requests as they become available... */
|
||||
add_to_blkdev_list_tail(blkif);
|
||||
maybe_trigger_blkio_schedule();
|
||||
}
|
||||
|
||||
} else if (RING_HAS_UNCONSUMED_REQUESTS(blk_ring)) {
|
||||
more_to_do = 1;
|
||||
|
||||
}
|
||||
spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
|
||||
|
||||
if (more_to_do) {
|
||||
atomic_inc(&blkif->io_pending);
|
||||
wake_up(&blkif->wq);
|
||||
}
|
||||
if (notify)
|
||||
notify_remote_via_irq(blkif->irq);
|
||||
}
|
||||
|
||||
void blkif_deschedule(blkif_t *blkif)
|
||||
{
|
||||
remove_from_blkdev_list(blkif);
|
||||
}
|
||||
|
||||
static int __init blkif_init(void)
|
||||
{
|
||||
int i;
|
||||
struct page *page;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < MMAP_PAGES; i++)
|
||||
pending_grant_handles[i] = BLKBACK_INVALID_HANDLE;
|
||||
int i;
|
||||
|
||||
if (xen_init() < 0)
|
||||
return -ENODEV;
|
||||
|
||||
mmap_pages = blkif_reqs * BLKIF_MAX_SEGMENTS_PER_REQUEST;
|
||||
pending_reqs = kmalloc(sizeof(pending_reqs[0]) *
|
||||
blkif_reqs, GFP_KERNEL);
|
||||
pending_grant_handles = kmalloc(sizeof(pending_grant_handles[0]) *
|
||||
mmap_pages, GFP_KERNEL);
|
||||
pending_vaddrs = kmalloc(sizeof(pending_vaddrs[0]) *
|
||||
mmap_pages, GFP_KERNEL);
|
||||
if (!pending_reqs || !pending_grant_handles || !pending_vaddrs) {
|
||||
printk("%s: out of memory\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
blkif_interface_init();
|
||||
|
||||
|
||||
#ifdef __ia64__
|
||||
{
|
||||
extern unsigned long alloc_empty_foreign_map_page_range(unsigned long pages);
|
||||
int i;
|
||||
|
||||
mmap_vstart = alloc_empty_foreign_map_page_range(MMAP_PAGES);
|
||||
printk("Allocated mmap_vstart: 0x%lx\n", mmap_vstart);
|
||||
for(i = 0; i < MMAP_PAGES; i++)
|
||||
pending_vaddrs[i] = mmap_vstart + (i << PAGE_SHIFT);
|
||||
BUG_ON(mmap_vstart == NULL);
|
||||
}
|
||||
#else
|
||||
page = balloon_alloc_empty_page_range(MMAP_PAGES);
|
||||
extern unsigned long alloc_empty_foreign_map_page_range(
|
||||
unsigned long pages);
|
||||
mmap_vstart = (unsigned long)
|
||||
alloc_empty_foreign_map_page_range(mmap_pages);
|
||||
#else /* ! ia64 */
|
||||
page = balloon_alloc_empty_page_range(mmap_pages);
|
||||
BUG_ON(page == NULL);
|
||||
mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
|
||||
#endif
|
||||
printk("%s: reqs=%d, pages=%d, mmap_vstart=0x%lx\n",
|
||||
__FUNCTION__, blkif_reqs, mmap_pages, mmap_vstart);
|
||||
BUG_ON(mmap_vstart == 0);
|
||||
for (i = 0; i < mmap_pages; i++) {
|
||||
pending_vaddrs[i] = mmap_vstart + (i << PAGE_SHIFT);
|
||||
pending_grant_handles[i] = BLKBACK_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
pending_cons = 0;
|
||||
pending_prod = MAX_PENDING_REQS;
|
||||
memset(pending_reqs, 0, sizeof(pending_reqs));
|
||||
for (i = 0; i < MAX_PENDING_REQS; i++)
|
||||
pending_ring[i] = i;
|
||||
INIT_LIST_HEAD(&pending_free);
|
||||
|
||||
for (i = 0; i < blkif_reqs; i++)
|
||||
list_add_tail(&pending_reqs[i].free_list, &pending_free);
|
||||
|
||||
spin_lock_init(&blkio_schedule_list_lock);
|
||||
INIT_LIST_HEAD(&blkio_schedule_list);
|
||||
|
||||
ret = kernel_thread(blkio_schedule, NULL, CLONE_FS | CLONE_FILES);
|
||||
BUG_ON(ret < 0);
|
||||
|
||||
blkif_xenbus_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,10 +60,20 @@ typedef struct blkif_st {
|
||||
/* Is this a blktap frontend */
|
||||
unsigned int is_blktap;
|
||||
#endif
|
||||
struct list_head blkdev_list;
|
||||
spinlock_t blk_ring_lock;
|
||||
atomic_t refcnt;
|
||||
|
||||
wait_queue_head_t wq;
|
||||
struct task_struct *xenblkd;
|
||||
atomic_t io_pending;
|
||||
request_queue_t *plug;
|
||||
|
||||
/* statistics */
|
||||
unsigned long st_print;
|
||||
int st_rd_req;
|
||||
int st_wr_req;
|
||||
int st_oo_req;
|
||||
|
||||
struct work_struct free_work;
|
||||
|
||||
grant_handle_t shmem_handle;
|
||||
@@ -101,11 +111,10 @@ int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation);
|
||||
|
||||
void blkif_interface_init(void);
|
||||
|
||||
void blkif_deschedule(blkif_t *blkif);
|
||||
|
||||
void blkif_xenbus_init(void);
|
||||
|
||||
irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs);
|
||||
int blkif_schedule(void *arg);
|
||||
|
||||
void update_blkif_status(blkif_t *blkif);
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ blkif_t *alloc_blkif(domid_t domid)
|
||||
blkif->status = DISCONNECTED;
|
||||
spin_lock_init(&blkif->blk_ring_lock);
|
||||
atomic_set(&blkif->refcnt, 1);
|
||||
init_waitqueue_head(&blkif->wq);
|
||||
blkif->st_print = jiffies;
|
||||
|
||||
return blkif;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <asm-xen/xenbus.h>
|
||||
#include "common.h"
|
||||
|
||||
@@ -92,6 +93,8 @@ static int blkback_remove(struct xenbus_device *dev)
|
||||
}
|
||||
if (be->blkif) {
|
||||
be->blkif->status = DISCONNECTED;
|
||||
if (be->blkif->xenblkd)
|
||||
kthread_stop(be->blkif->xenblkd);
|
||||
blkif_put(be->blkif);
|
||||
be->blkif = NULL;
|
||||
}
|
||||
@@ -220,6 +223,17 @@ static void backend_changed(struct xenbus_watch *watch,
|
||||
return;
|
||||
}
|
||||
|
||||
be->blkif->xenblkd = kthread_run(blkif_schedule, be->blkif,
|
||||
"xvd %d %02x:%02x",
|
||||
be->blkif->domid,
|
||||
be->major, be->minor);
|
||||
if (IS_ERR(be->blkif->xenblkd)) {
|
||||
err = PTR_ERR(be->blkif->xenblkd);
|
||||
be->blkif->xenblkd = NULL;
|
||||
xenbus_dev_error(dev, err, "start xenblkd");
|
||||
return;
|
||||
}
|
||||
|
||||
device_create_file(&dev->dev, &dev_attr_physical_device);
|
||||
device_create_file(&dev->dev, &dev_attr_mode);
|
||||
|
||||
|
||||
@@ -55,7 +55,8 @@ typedef struct netif_st {
|
||||
/* The shared rings and indexes. */
|
||||
netif_tx_back_ring_t tx;
|
||||
netif_rx_back_ring_t rx;
|
||||
struct vm_struct *comms_area;
|
||||
struct vm_struct *tx_comms_area;
|
||||
struct vm_struct *rx_comms_area;
|
||||
|
||||
/* Allow netif_be_start_xmit() to peek ahead in the rx request ring. */
|
||||
RING_IDX rx_req_cons_peek;
|
||||
|
||||
@@ -117,14 +117,14 @@ static int map_frontend_pages(
|
||||
struct gnttab_map_grant_ref op;
|
||||
int ret;
|
||||
|
||||
op.host_addr = (unsigned long)netif->comms_area->addr;
|
||||
op.host_addr = (unsigned long)netif->tx_comms_area->addr;
|
||||
op.flags = GNTMAP_host_map;
|
||||
op.ref = tx_ring_ref;
|
||||
op.dom = netif->domid;
|
||||
|
||||
lock_vm_area(netif->comms_area);
|
||||
lock_vm_area(netif->tx_comms_area);
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
|
||||
unlock_vm_area(netif->comms_area);
|
||||
unlock_vm_area(netif->tx_comms_area);
|
||||
BUG_ON(ret);
|
||||
|
||||
if (op.status) {
|
||||
@@ -135,14 +135,14 @@ static int map_frontend_pages(
|
||||
netif->tx_shmem_ref = tx_ring_ref;
|
||||
netif->tx_shmem_handle = op.handle;
|
||||
|
||||
op.host_addr = (unsigned long)netif->comms_area->addr + PAGE_SIZE;
|
||||
op.host_addr = (unsigned long)netif->rx_comms_area->addr;
|
||||
op.flags = GNTMAP_host_map;
|
||||
op.ref = rx_ring_ref;
|
||||
op.dom = netif->domid;
|
||||
|
||||
lock_vm_area(netif->comms_area);
|
||||
lock_vm_area(netif->rx_comms_area);
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
|
||||
unlock_vm_area(netif->comms_area);
|
||||
unlock_vm_area(netif->rx_comms_area);
|
||||
BUG_ON(ret);
|
||||
|
||||
if (op.status) {
|
||||
@@ -161,22 +161,22 @@ static void unmap_frontend_pages(netif_t *netif)
|
||||
struct gnttab_unmap_grant_ref op;
|
||||
int ret;
|
||||
|
||||
op.host_addr = (unsigned long)netif->comms_area->addr;
|
||||
op.host_addr = (unsigned long)netif->tx_comms_area->addr;
|
||||
op.handle = netif->tx_shmem_handle;
|
||||
op.dev_bus_addr = 0;
|
||||
|
||||
lock_vm_area(netif->comms_area);
|
||||
lock_vm_area(netif->tx_comms_area);
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
|
||||
unlock_vm_area(netif->comms_area);
|
||||
unlock_vm_area(netif->tx_comms_area);
|
||||
BUG_ON(ret);
|
||||
|
||||
op.host_addr = (unsigned long)netif->comms_area->addr + PAGE_SIZE;
|
||||
op.host_addr = (unsigned long)netif->rx_comms_area->addr;
|
||||
op.handle = netif->rx_shmem_handle;
|
||||
op.dev_bus_addr = 0;
|
||||
|
||||
lock_vm_area(netif->comms_area);
|
||||
lock_vm_area(netif->rx_comms_area);
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
|
||||
unlock_vm_area(netif->comms_area);
|
||||
unlock_vm_area(netif->rx_comms_area);
|
||||
BUG_ON(ret);
|
||||
}
|
||||
|
||||
@@ -195,20 +195,23 @@ int netif_map(netif_t *netif, unsigned long tx_ring_ref,
|
||||
if (netif->irq)
|
||||
return 0;
|
||||
|
||||
netif->comms_area = alloc_vm_area(2*PAGE_SIZE);
|
||||
if (netif->comms_area == NULL)
|
||||
netif->tx_comms_area = alloc_vm_area(PAGE_SIZE);
|
||||
netif->rx_comms_area = alloc_vm_area(PAGE_SIZE);
|
||||
if (netif->tx_comms_area == NULL || netif->rx_comms_area == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
err = map_frontend_pages(netif, tx_ring_ref, rx_ring_ref);
|
||||
if (err) {
|
||||
free_vm_area(netif->comms_area);
|
||||
free_vm_area(netif->tx_comms_area);
|
||||
free_vm_area(netif->rx_comms_area);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = HYPERVISOR_event_channel_op(&op);
|
||||
if (err) {
|
||||
unmap_frontend_pages(netif);
|
||||
free_vm_area(netif->comms_area);
|
||||
free_vm_area(netif->tx_comms_area);
|
||||
free_vm_area(netif->rx_comms_area);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -218,11 +221,11 @@ int netif_map(netif_t *netif, unsigned long tx_ring_ref,
|
||||
netif->evtchn, netif_be_int, 0, netif->dev->name, netif);
|
||||
disable_irq(netif->irq);
|
||||
|
||||
txs = (netif_tx_sring_t *)netif->comms_area->addr;
|
||||
txs = (netif_tx_sring_t *)netif->tx_comms_area->addr;
|
||||
BACK_RING_INIT(&netif->tx, txs, PAGE_SIZE);
|
||||
|
||||
rxs = (netif_rx_sring_t *)
|
||||
((char *)netif->comms_area->addr + PAGE_SIZE);
|
||||
((char *)netif->rx_comms_area->addr);
|
||||
BACK_RING_INIT(&netif->rx, rxs, PAGE_SIZE);
|
||||
|
||||
netif->rx_req_cons_peek = 0;
|
||||
@@ -255,7 +258,8 @@ static void free_netif_callback(void *arg)
|
||||
|
||||
if (netif->tx.sring) {
|
||||
unmap_frontend_pages(netif);
|
||||
free_vm_area(netif->comms_area);
|
||||
free_vm_area(netif->tx_comms_area);
|
||||
free_vm_area(netif->rx_comms_area);
|
||||
}
|
||||
|
||||
free_netdev(netif->dev);
|
||||
|
||||
@@ -1171,11 +1171,6 @@ class XendDomainInfo:
|
||||
|
||||
xc.domain_setcpuweight(self.domid, self.info['cpu_weight'])
|
||||
|
||||
m = self.image.getDomainMemory(self.info['memory'] * 1024)
|
||||
balloon.free(m)
|
||||
xc.domain_setmaxmem(self.domid, m)
|
||||
xc.domain_memory_increase_reservation(self.domid, m, 0, 0)
|
||||
|
||||
# repin domain vcpus if a restricted cpus list is provided
|
||||
# this is done prior to memory allocation to aide in memory
|
||||
# distribution for NUMA systems.
|
||||
@@ -1186,6 +1181,11 @@ class XendDomainInfo:
|
||||
cpu = [ int( cpus[v % len(cpus)] ) ]
|
||||
xc.domain_pincpu(self.domid, v, cpu)
|
||||
|
||||
m = self.image.getDomainMemory(self.info['memory'] * 1024)
|
||||
balloon.free(m)
|
||||
xc.domain_setmaxmem(self.domid, m)
|
||||
xc.domain_memory_increase_reservation(self.domid, m, 0, 0)
|
||||
|
||||
self.createChannels()
|
||||
|
||||
channel_details = self.image.createImage()
|
||||
|
||||
@@ -38,10 +38,14 @@ class TPMifController(DevController):
|
||||
def getDeviceDetails(self, config):
|
||||
"""@see DevController.getDeviceDetails"""
|
||||
|
||||
devid = int(sxp.child_value(config, 'pref_instance', '0'))
|
||||
log.info("The domain has a TPM with instance %d." % devid)
|
||||
devid = self.allocateDeviceID()
|
||||
inst = int(sxp.child_value(config, 'pref_instance', '-1'))
|
||||
if inst == -1:
|
||||
inst = int(sxp.child_value(config, 'instance' , '0'))
|
||||
|
||||
back = { 'pref_instance' : "%i" % devid }
|
||||
log.info("The domain has a TPM with instance %d and devid %d.",
|
||||
inst, devid)
|
||||
back = { 'pref_instance' : "%i" % inst }
|
||||
front = { 'handle' : "%i" % devid }
|
||||
|
||||
return (devid, back, front)
|
||||
|
||||
+59
-33
@@ -1,16 +1,19 @@
|
||||
XEN_ROOT = ../..
|
||||
include $(XEN_ROOT)/tools/Rules.mk
|
||||
|
||||
SRCS = secpol_tool.c
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Werror
|
||||
CFLAGS += -O3
|
||||
CFLAGS += -fno-strict-aliasing
|
||||
CFLAGS += -I. -I/usr/include/libxml2
|
||||
CFLAGS_XML2BIN += $(shell xml2-config --cflags --libs )
|
||||
#if above does not work, try -L/usr/lib -lxml2 -lz -lpthread -lm
|
||||
CFLAGS += -I.
|
||||
|
||||
CPPFLAGS += -MMD -MF .$*.d
|
||||
PROG_DEPS = .*.d
|
||||
|
||||
XML2VERSION = $(shell xml2-config --version )
|
||||
VALIDATE_SCHEMA=$(shell if [[ $(XML2VERSION) < 2.6.20 ]]; then echo ""; else echo "-DVALIDATE_SCHEMA"; fi; )
|
||||
CFLAGS += $(shell xml2-config --cflags )
|
||||
CFLAGS += $(shell if [[ $(XML2VERSION) < 2.6.20 ]]; then echo ""; else echo "-DVALIDATE_SCHEMA"; fi )
|
||||
LDFLAGS += $(shell xml2-config --libs ) # if this does not work, try -L/usr/lib -lxml2 -lz -lpthread -lm
|
||||
|
||||
ifeq ($(ACM_DEFAULT_SECURITY_POLICY),ACM_NULL_POLICY)
|
||||
POLICY=null
|
||||
@@ -24,48 +27,71 @@ endif
|
||||
ifeq ($(ACM_DEFAULT_SECURITY_POLICY),ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY)
|
||||
POLICY=chwall_ste
|
||||
endif
|
||||
POLICYFILE=./policies/$(POLICY)/$(POLICY).bin
|
||||
|
||||
SRCS_TOOL = secpol_tool.c
|
||||
OBJS_TOOL := $(patsubst %.c,%.o,$(filter %.c,$(SRCS_TOOL)))
|
||||
SRCS_XML2BIN = secpol_xml2bin.c secpol_xml2bin.h
|
||||
OBJS_XML2BIN := $(patsubst %.c,%.o,$(filter %.c,$(SRCS_XML2BIN)))
|
||||
SRCS_GETD = get_decision.c
|
||||
OBJS_GETD := $(patsubst %.c,%.o,$(filter %.c,$(SRCS_GETD)))
|
||||
|
||||
ACM_INST_TOOLS = xensec_tool xensec_xml2bin
|
||||
ACM_NOINST_TOOLS = get_decision
|
||||
ACM_OBJS = $(OBJS_TOOL) $(OBJS_XML2BIN) $(OBJS_GETD)
|
||||
ACM_SCRIPTS = getlabel.sh setlabel.sh updategrub.sh labelfuncs.sh
|
||||
|
||||
ACM_CONFIG_DIR = /etc/xen/acm-security
|
||||
ACM_POLICY_DIR = $(ACM_CONFIG_DIR)/policies
|
||||
ACM_SCRIPT_DIR = $(ACM_CONFIG_DIR)/scripts
|
||||
|
||||
ACM_SCHEMA = security_policy.xsd
|
||||
ACM_EXAMPLES = null chwall ste chwall_ste
|
||||
ACM_POLICY_SUFFIX = security_policy.xml
|
||||
ACM_LABEL_SUFFIX = security_label_template.xml
|
||||
|
||||
ifeq ($(ACM_SECURITY),y)
|
||||
all: build
|
||||
|
||||
install:all
|
||||
|
||||
default:all
|
||||
install: all $(ACM_CONFIG_FILE)
|
||||
$(INSTALL_DIR) -p $(DESTDIR)/usr/sbin
|
||||
$(INSTALL_PROG) -p $(ACM_INST_TOOLS) $(DESTDIR)/usr/sbin
|
||||
$(INSTALL_DIR) -p $(DESTDIR)$(ACM_CONFIG_DIR)
|
||||
$(INSTALL_DIR) -p $(DESTDIR)$(ACM_POLICY_DIR)
|
||||
$(INSTALL_DATA) -p policies/$(ACM_SCHEMA) $(DESTDIR)$(ACM_POLICY_DIR)
|
||||
for i in $(ACM_EXAMPLES); do \
|
||||
$(INSTALL_DIR) -p $(DESTDIR)$(ACM_POLICY_DIR)/$$i; \
|
||||
$(INSTALL_DATA) -p policies/$$i/$$i-$(ACM_POLICY_SUFFIX) $(DESTDIR)$(ACM_POLICY_DIR)/$$i; \
|
||||
$(INSTALL_DATA) -p policies/$$i/$$i-$(ACM_LABEL_SUFFIX) $(DESTDIR)$(ACM_POLICY_DIR)/$$i; \
|
||||
done
|
||||
$(INSTALL_DIR) -p $(DESTDIR)$(ACM_SCRIPT_DIR)
|
||||
$(INSTALL_PROG) -p $(ACM_SCRIPTS) $(DESTDIR)$(ACM_SCRIPT_DIR)
|
||||
else
|
||||
all:
|
||||
|
||||
install:
|
||||
|
||||
default:
|
||||
endif
|
||||
|
||||
build: mk-symlinks
|
||||
$(MAKE) secpol_tool
|
||||
$(MAKE) secpol_xml2bin
|
||||
$(MAKE) get_decision
|
||||
chmod 700 ./setlabel.sh
|
||||
chmod 700 ./updategrub.sh
|
||||
chmod 700 ./getlabel.sh
|
||||
build: mk-symlinks $(ACM_INST_TOOLS) $(ACM_NOINST_TOOLS)
|
||||
chmod 700 $(ACM_SCRIPTS)
|
||||
|
||||
secpol_tool : secpol_tool.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $<
|
||||
xensec_tool: $(OBJS_TOOL)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
|
||||
|
||||
secpol_xml2bin : secpol_xml2bin.c secpol_xml2bin.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_XML2BIN) $(VALIDATE_SCHEMA) -o $@ $<
|
||||
xensec_xml2bin: $(OBJS_XML2BIN)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
|
||||
|
||||
get_decision: $(OBJS_GETD)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -rf secpol_tool secpol_xml2bin xen get_decision
|
||||
$(RM) $(ACM_INST_TOOLS) $(ACM_NOINST_TOOLS)
|
||||
$(RM) $(ACM_OBJS)
|
||||
$(RM) $(PROG_DEPS)
|
||||
$(RM) -r xen
|
||||
|
||||
policy_clean:
|
||||
rm -rf policies/*/*.bin policies/*/*.map
|
||||
mrproper: clean
|
||||
|
||||
mrproper: clean policy_clean
|
||||
boot_install: install
|
||||
$(ACM_SCRIPT_DIR)/updategrub.sh $(POLICY) $(KERNEL_VERSION)
|
||||
|
||||
|
||||
$(POLICYFILE) : build
|
||||
@./secpol_xml2bin $(POLICY) > /dev/null
|
||||
|
||||
boot_install: $(POLICYFILE)
|
||||
@cp $(POLICYFILE) /boot
|
||||
@./updategrub.sh $(POLICY) $(PWD)/$(XEN_ROOT)
|
||||
-include $(PROG_DEPS)
|
||||
+43
-39
@@ -9,23 +9,23 @@
|
||||
# and to label domains and resources.
|
||||
##
|
||||
|
||||
We will show how to install and use the chwall_ste policy.
|
||||
We will show how to install and use the example chwall_ste policy.
|
||||
Other policies work similarly. Feedback welcome!
|
||||
|
||||
|
||||
|
||||
1. Using secpol_xml2bin to translate the chwall_ste policy:
|
||||
1. Using xensec_xml2bin to translate the chwall_ste policy:
|
||||
===========================================================
|
||||
|
||||
#tools/security/secpol_xml2bin chwall_ste
|
||||
#xensec_xml2bin chwall_ste
|
||||
|
||||
Successful execution should print:
|
||||
|
||||
[root@laptopxn security]# ./secpol_xml2bin chwall_ste
|
||||
Validating label file policies/chwall_ste/chwall_ste-security_label_template.xml...
|
||||
XML Schema policies/security_policy.xsd valid.
|
||||
Validating policy file policies/chwall_ste/chwall_ste-security_policy.xml...
|
||||
XML Schema policies/security_policy.xsd valid.
|
||||
[root@laptopxn security]# xensec_xml2bin chwall_ste
|
||||
Validating label file /etc/xen/acm-security/policies/chwall_ste/chwall_ste-security_label_template.xml...
|
||||
XML Schema /etc/xen/acm-security/policies/security_policy.xsd valid.
|
||||
Validating policy file /etc/xen/acm-security/policies/chwall_ste/chwall_ste-security_policy.xml...
|
||||
XML Schema /etc/xen/acm-security/policies/security_policy.xsd valid.
|
||||
Creating ssid mappings ...
|
||||
Creating label mappings ...
|
||||
Max chwall labels: 7
|
||||
@@ -35,10 +35,15 @@ Successful execution should print:
|
||||
Max ste-types: 6
|
||||
Max ste-ssids: 10
|
||||
|
||||
The tool looks in directory policies/chwall_ste for
|
||||
By default, the tool looks in directory /etc/xen/acm-security/policies
|
||||
for a directory that matches the policy name (i.e. chwall_ste) to find
|
||||
the label and policy files.
|
||||
The '-d' option can be used to override the /etc/xen/acm-security/policies
|
||||
directory, for example if running the tool in the Xen security tool build
|
||||
directory.
|
||||
|
||||
The default policy directory structure under tools/security looks like:
|
||||
The default policy directory structure under /etc/xen/acm-security (and
|
||||
the Xen security tool build directory - tools/security) looks like:
|
||||
|
||||
policies
|
||||
|-- security_policy.xsd
|
||||
@@ -55,25 +60,25 @@ policies
|
||||
|-- ste-security_label_template.xml
|
||||
`-- ste-security_policy.xml
|
||||
|
||||
policies/security_policy.xsd contains the schema against which both the
|
||||
The security_policy.xsd file contains the schema against which both the
|
||||
label-template and the policy files must validate during translation.
|
||||
|
||||
policies/chwall_ste/chwall_ste-security_policy.xml defines the
|
||||
policies and the types known to the policies.
|
||||
The files ending in -security_policy.xml define the policies and the
|
||||
types known to the policies.
|
||||
|
||||
policies/chwall_ste/chwall_ste-security_label_template.xml contains
|
||||
label definitions that group chwall and ste types together and make
|
||||
them easier to use for users
|
||||
The files ending in -security_label_template.xml contain the label
|
||||
definitions that group types together and make them easier to use for
|
||||
users.
|
||||
|
||||
After executing the above secpol_xml2bin command, you will find 2 new
|
||||
files in the policies/chwall_ste sub-directory:
|
||||
After executing the above xensec_xml2bin command, you will find 2 new
|
||||
files in the /etc/xen/acm-security/policies/chwall_ste sub-directory:
|
||||
|
||||
policies/chwall_ste/chwall_ste.map ... this file includes the mapping
|
||||
of names from the xml files into their binary code representation.
|
||||
chwall_ste.map ... this file includes the mapping
|
||||
of names from the xml files into their binary code representation.
|
||||
|
||||
policies/chwall_ste/chwall_ste.bin ... this is the binary policy file,
|
||||
the result of parsing the xml files and using the mapping to extract a
|
||||
binary version that can be loaded into the hypervisor.
|
||||
chwall_ste.bin ... this is the binary policy file,
|
||||
the result of parsing the xml files and using the mapping to extract a
|
||||
binary version that can be loaded into the hypervisor.
|
||||
|
||||
|
||||
|
||||
@@ -85,13 +90,13 @@ please refer to install.txt for instructions.
|
||||
|
||||
To activate the policy from the command line (assuming that the
|
||||
currently established policy is the minimal boot-policy that is
|
||||
hard-coded into the hypervisor:
|
||||
hard-coded into the hypervisor):
|
||||
|
||||
# ./secpol_tool loadpolicy policies/chwall_ste/chwall_ste.bin
|
||||
# xensec_tool loadpolicy /etc/xen/acm-security/policies/chwall_ste/chwall_ste.bin
|
||||
|
||||
To activate the policy at next reboot:
|
||||
|
||||
# cp policies/chwall_ste/chwall_ste.bin /boot
|
||||
# cp /etc/xen/acm-security/policies/chwall_ste/chwall_ste.bin /boot
|
||||
|
||||
Add a module line to your /boot/grub/grub.conf Xen entry.
|
||||
My boot entry with chwall_ste enabled looks like this:
|
||||
@@ -129,12 +134,12 @@ assign labels to user domains.
|
||||
|
||||
To show available labels for the chwall_ste policy:
|
||||
|
||||
#tools/security/setlabel.sh -l
|
||||
# /etc/xen/acm-security/scripts/setlabel.sh -l
|
||||
|
||||
lists all available labels. For the default chwall_ste it should print
|
||||
the following:
|
||||
|
||||
[root@laptopxn security]# ./setlabel.sh -l chwall_ste
|
||||
[root@laptopxn security]# /etc/xen/acm-security/scripts/setlabel.sh -l chwall_ste
|
||||
The following labels are available:
|
||||
dom_SystemManagement
|
||||
dom_HomeBanking
|
||||
@@ -156,8 +161,8 @@ Setlabel.sh only prints VM labels (which we have prefixed with "dom_")
|
||||
since only those are used at this time.
|
||||
|
||||
If you would like to assign the dom_HomeBanking label to one of your
|
||||
user domains (which you hopefully keep clean), look at an example
|
||||
domain configuration homebanking.xm:
|
||||
user domains (which you hopefully keep clean), look at the hypothetical
|
||||
domain configuration contained in /etc/xen/homebanking.xm:
|
||||
|
||||
#------HOMEBANKING---------
|
||||
kernel = "/boot/vmlinuz-2.6.12-xenU"
|
||||
@@ -172,7 +177,7 @@ domain configuration homebanking.xm:
|
||||
|
||||
Now we label this domain
|
||||
|
||||
[root@laptopxn security]# ./setlabel.sh homebanking.xm dom_HomeBanking chwall_ste
|
||||
[root@laptopxn security]# /etc/xen/acm-securit/scripts/setlabel.sh /etc/xen/homebanking.xm dom_HomeBanking chwall_ste
|
||||
Mapped label 'dom_HomeBanking' to ssidref '0x00020002'.
|
||||
|
||||
The domain configuration my look now like:
|
||||
@@ -223,9 +228,8 @@ because of the defined conflict set
|
||||
<type>cw_Distrusted</type>
|
||||
</conflictset>
|
||||
|
||||
(in policies/chwall_ste/chwall_ste-security_policy.xml), which says
|
||||
that only one of the types cw_sensitive and cw_Distrusted can run at a
|
||||
time.
|
||||
(in chwall_ste-security_policy.xml), which says that only one of the
|
||||
types cw_Sensitive and cw_Distrusted can run at a time.
|
||||
|
||||
If you save or shutdown the HomeBanking domain, you will be able to
|
||||
start the "Fun" domain. You can look into the Xen log to see if a
|
||||
@@ -255,15 +259,15 @@ a) the policy definition (types etc.) file
|
||||
b) the label template definition (labels etc.) file
|
||||
|
||||
If your policy name is "mypolicy", you need to create a
|
||||
subdirectory mypolicy in tools/security/policies.
|
||||
subdirectory mypolicy in /etc/xen/acm-security/policies.
|
||||
|
||||
Then you create
|
||||
tools/security/policies/mypolicy/mypolicy-security_policy.xml and
|
||||
tools/security/policies/mypolicy/mypolicy-security_label_template.xml.
|
||||
/etc/xen/acm-security/policies/mypolicy/mypolicy-security_policy.xml and
|
||||
/etc/xen/acm-security/policies/mypolicy/mypolicy-security_label_template.xml.
|
||||
|
||||
You need to keep to the schema as defined in
|
||||
tools/security/security_policy.xsd since the translation tool
|
||||
secpol_xml2bin is written against this schema.
|
||||
/etc/xen/acm-security/security_policy.xsd since the translation tool
|
||||
xensec_xml2bin is written against this schema.
|
||||
|
||||
If you keep to the security policy schema, then you can use all the
|
||||
tools described above. Refer to install.txt to install it.
|
||||
+29
-68
@@ -32,20 +32,24 @@ fi
|
||||
|
||||
|
||||
export PATH=$PATH:.
|
||||
source labelfuncs.sh
|
||||
dir=`dirname $0`
|
||||
source $dir/labelfuncs.sh
|
||||
|
||||
usage ()
|
||||
{
|
||||
prg=`basename $0`
|
||||
echo "Use this tool to display the label of a domain or the label that is
|
||||
corresponding to an ssidref given the name of the running policy.
|
||||
|
||||
Usage: $0 -sid <ssidref> [<policy name>] or
|
||||
$0 -dom <domid> [<policy name>]
|
||||
Usage: $prg -sid <ssidref> [<policy name> [<policy dir>]] or
|
||||
$prg -dom <domid> [<policy name> [<policy dir>]]
|
||||
|
||||
policy name : the name of the policy, i.e. 'chwall'
|
||||
If the policy name is omitted, the grub.conf
|
||||
entry of the running system is tried to be read
|
||||
and the policy name determined from there.
|
||||
policy dir : the directory where the <policy name> policy is located
|
||||
The default location is '/etc/xen/acm-security/policies'
|
||||
ssidref : an ssidref in hex or decimal format, i.e., '0x00010002'
|
||||
or '65538'
|
||||
domid : id of the domain, i.e., '1'; Use numbers from the 2nd
|
||||
@@ -55,79 +59,36 @@ domid : id of the domain, i.e., '1'; Use numbers from the 2nd
|
||||
|
||||
|
||||
|
||||
if [ "$1" == "-?" ]; then
|
||||
mode="usage"
|
||||
if [ "$1" == "-h" ]; then
|
||||
usage
|
||||
exit 0
|
||||
elif [ "$1" == "-dom" ]; then
|
||||
mode="domid"
|
||||
shift
|
||||
elif [ "$1" == "-sid" ]; then
|
||||
mode="sid"
|
||||
shift
|
||||
elif [ "$1" == "" ]; then
|
||||
else
|
||||
usage
|
||||
exit -1
|
||||
fi
|
||||
|
||||
|
||||
if [ "$mode" == "usage" ]; then
|
||||
usage
|
||||
elif [ "$mode" == "domid" ]; then
|
||||
if [ "$2" == "" ]; then
|
||||
findGrubConf
|
||||
ret=$?
|
||||
if [ $ret -eq 0 ]; then
|
||||
echo "Could not find grub.conf"
|
||||
exit -1;
|
||||
fi
|
||||
findPolicyInGrub $grubconf
|
||||
if [ "$policy" != "" ]; then
|
||||
echo "Assuming policy to be '$policy'.";
|
||||
else
|
||||
echo "Could not find policy."
|
||||
exit -1;
|
||||
fi
|
||||
else
|
||||
policy=$2
|
||||
fi
|
||||
findMapFile $policy
|
||||
res=$?
|
||||
if [ "$res" != "0" ]; then
|
||||
getSSIDUsingSecpolTool $1
|
||||
res=$?
|
||||
if [ "$res" != "0" ]; then
|
||||
translateSSIDREF $ssid $mapfile
|
||||
else
|
||||
echo "Could not determine the SSID of the domain."
|
||||
fi
|
||||
else
|
||||
echo "Could not find map file for policy '$policy'."
|
||||
fi
|
||||
elif [ "$mode" == "sid" ]; then
|
||||
if [ "$2" == "" ]; then
|
||||
findGrubConf
|
||||
ret=$?
|
||||
if [ $ret -eq 0 ]; then
|
||||
echo "Could not find grub.conf"
|
||||
exit -1;
|
||||
fi
|
||||
findPolicyInGrub $grubconf
|
||||
if [ "$policy" != "" ]; then
|
||||
echo "Assuming policy to be '$policy'.";
|
||||
else
|
||||
echo "Could not find policy."
|
||||
exit -1;
|
||||
fi
|
||||
else
|
||||
policy=$2
|
||||
fi
|
||||
findMapFile $policy
|
||||
res=$?
|
||||
if [ "$res" != "0" ]; then
|
||||
translateSSIDREF $1 $mapfile
|
||||
else
|
||||
echo "Could not find map file for policy '$policy'."
|
||||
fi
|
||||
|
||||
else
|
||||
usage
|
||||
setPolicyVars $2 $3
|
||||
findMapFile $policy $policydir
|
||||
ret=$?
|
||||
if [ $ret -eq 0 ]; then
|
||||
echo "Could not find map file for policy '$policy'."
|
||||
exit -1
|
||||
fi
|
||||
|
||||
if [ "$mode" == "domid" ]; then
|
||||
getSSIDUsingSecpolTool $1
|
||||
ret=$?
|
||||
if [ $ret -eq 0 ]; then
|
||||
echo "Could not determine the SSID of the domain."
|
||||
exit -1
|
||||
fi
|
||||
translateSSIDREF $ssid $mapfile
|
||||
else # mode == sid
|
||||
translateSSIDREF $1 $mapfile
|
||||
fi
|
||||
@@ -41,11 +41,11 @@ exclusively (chwall_ste --> {chwall, ste}).
|
||||
# make
|
||||
|
||||
manual steps (alternative to make boot_install):
|
||||
#./secpol_xml2bin chwall_ste
|
||||
#cp policies/chwall_ste/chwall_ste.bin /boot
|
||||
#edit /boot/grub/grub.conf
|
||||
# ./xensec_xml2bin -d policies/ chwall_ste
|
||||
# cp policies/chwall_ste/chwall_ste.bin /boot
|
||||
# edit /boot/grub/grub.conf
|
||||
add the follwoing line to your xen boot entry:
|
||||
"module chwall_ste.bin"
|
||||
"module /boot/chwall_ste.bin"
|
||||
|
||||
alternatively, you can try our automatic translation and
|
||||
installation of the policy:
|
||||
@@ -61,9 +61,9 @@ exclusively (chwall_ste --> {chwall, ste}).
|
||||
3. reboot into the newly compiled hypervisor
|
||||
|
||||
after boot
|
||||
#xm dmesg should show an entry about the policy being loaded
|
||||
# xm dmesg should show an entry about the policy being loaded
|
||||
during the boot process
|
||||
|
||||
#tools/security/secpol_tool getpolicy
|
||||
# xensec_tool getpolicy
|
||||
should print the new chwall_ste binary policy representation
|
||||
|
||||
+158
-34
@@ -17,10 +17,53 @@
|
||||
#
|
||||
|
||||
|
||||
#Some global variables for tools using this module
|
||||
ACM_DEFAULT_ROOT="/etc/xen/acm-security"
|
||||
|
||||
# Set the policy and policydir variables
|
||||
# Parameters:
|
||||
# 1st : possible policy name
|
||||
# 2nd : possible policy directory
|
||||
# Results:
|
||||
# The variables policy and policydir will hold the values for locating
|
||||
# policy information
|
||||
# If there are no errors, the functions returns a '1',
|
||||
# a '0' otherwise.
|
||||
setPolicyVars ()
|
||||
{
|
||||
local ret
|
||||
# Set default values
|
||||
policydir="$ACM_DEFAULT_ROOT/policies"
|
||||
policy=""
|
||||
|
||||
if [ "$1" == "" ]; then
|
||||
findGrubConf
|
||||
ret=$?
|
||||
if [ $ret -eq 0 ]; then
|
||||
echo "Could not find grub.conf."
|
||||
return 0;
|
||||
fi
|
||||
findPolicyInGrub $grubconf
|
||||
if [ "$policy" == "" ]; then
|
||||
echo "Could not find policy in grub.conf. Looked for entry using kernel $linux."
|
||||
return 0;
|
||||
fi
|
||||
echo "Assuming policy to be '$policy'.";
|
||||
else
|
||||
policy=$1
|
||||
if [ "$2" != "" ]; then
|
||||
policydir=$2
|
||||
fi
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Find the mapfile given a policy nmame
|
||||
# Parameters:
|
||||
# 1st : the name of the policy whose map file is to be found, i.e.,
|
||||
# chwall
|
||||
# 2nd : the policy directory for locating the map file
|
||||
# Results:
|
||||
# The variable mapfile will hold the realtive path to the mapfile
|
||||
# for the given policy.
|
||||
@@ -28,16 +71,10 @@
|
||||
# a '0' otherwise.
|
||||
findMapFile ()
|
||||
{
|
||||
mapfile="./$1.map"
|
||||
mapfile="$2/$1/$1.map"
|
||||
if [ -r "$mapfile" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
mapfile="./policies/$1/$1.map"
|
||||
if [ -r "$mapfile" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -50,7 +87,7 @@ findMapFile ()
|
||||
# The variable primary will hold the name of the primary policy
|
||||
getPrimaryPolicy ()
|
||||
{
|
||||
mapfile=$1
|
||||
local mapfile=$1
|
||||
primary=`cat $mapfile | \
|
||||
awk ' \
|
||||
{ \
|
||||
@@ -71,7 +108,7 @@ getPrimaryPolicy ()
|
||||
# The variable secondary will hold the name of the secondary policy
|
||||
getSecondaryPolicy ()
|
||||
{
|
||||
mapfile=$1
|
||||
local mapfile=$1
|
||||
secondary=`cat $mapfile | \
|
||||
awk ' \
|
||||
{ \
|
||||
@@ -86,6 +123,10 @@ getSecondaryPolicy ()
|
||||
|
||||
#Return where the grub.conf file is.
|
||||
#I only know of one place it can be.
|
||||
#Returns:
|
||||
# 1 : if the file is writeable and readable
|
||||
# 2 : if the file is only readable
|
||||
# 0 : if the file does not exist
|
||||
findGrubConf()
|
||||
{
|
||||
grubconf="/boot/grub/grub.conf"
|
||||
@@ -112,16 +153,37 @@ findGrubConf()
|
||||
# kernel, i.e., 'vmlinuz-2.6.12-xen0'
|
||||
getLinuxVersion ()
|
||||
{
|
||||
path=$1
|
||||
local path
|
||||
local versionfile
|
||||
local lnx
|
||||
if [ "$1" == "" ]; then
|
||||
path="/lib/modules/*-xen0"
|
||||
else
|
||||
path="/lib/modules/$1"
|
||||
fi
|
||||
|
||||
linux=""
|
||||
for f in $path/linux-*-xen0 ; do
|
||||
versionfile=$f/include/linux/version.h
|
||||
versionfile=$f/build/include/linux/version.h
|
||||
if [ -r $versionfile ]; then
|
||||
lnx=`cat $versionfile | \
|
||||
grep UTS_RELEASE | \
|
||||
awk '{ \
|
||||
len=length($3); \
|
||||
print substr($3,2,len-2) }'`
|
||||
version=substr($3,2,len-2); \
|
||||
split(version,numbers,"."); \
|
||||
if (numbers[4]=="") { \
|
||||
printf("%s.%s.%s", \
|
||||
numbers[1], \
|
||||
numbers[2], \
|
||||
numbers[3]); \
|
||||
} else { \
|
||||
printf("%s.%s.%s[.0-9]*-xen0",\
|
||||
numbers[1], \
|
||||
numbers[2], \
|
||||
numbers[3]); \
|
||||
} \
|
||||
}'`
|
||||
fi
|
||||
if [ "$lnx" != "" ]; then
|
||||
linux="[./0-9a-zA-z]*$lnx"
|
||||
@@ -137,11 +199,12 @@ getLinuxVersion ()
|
||||
# Find out with which policy the hypervisor was booted with.
|
||||
# Parameters
|
||||
# 1st : The complete path to grub.conf, i.e., /boot/grub/grub.conf
|
||||
#
|
||||
# Result:
|
||||
# Sets the variable 'policy' to the name of the policy
|
||||
findPolicyInGrub ()
|
||||
{
|
||||
grubconf=$1
|
||||
linux=`uname -r`
|
||||
local grubconf=$1
|
||||
local linux=`uname -r`
|
||||
policy=`cat $grubconf | \
|
||||
awk -vlinux=$linux '{ \
|
||||
if ( $1 == "title" ) { \
|
||||
@@ -184,9 +247,9 @@ findPolicyInGrub ()
|
||||
# The funtion returns '1' on success, '0' on failure
|
||||
getSSIDUsingSecpolTool ()
|
||||
{
|
||||
domid=$1
|
||||
local domid=$1
|
||||
export PATH=$PATH:.
|
||||
ssid=`secpol_tool getssid -d $domid -f | \
|
||||
ssid=`xensec_tool getssid -d $domid -f | \
|
||||
grep -E "SSID:" | \
|
||||
awk '{ print $4 }'`
|
||||
|
||||
@@ -206,7 +269,7 @@ getSSIDUsingSecpolTool ()
|
||||
# high ssid values as integers.
|
||||
getSSIDLOHI ()
|
||||
{
|
||||
ssid=$1
|
||||
local ssid=$1
|
||||
ssidlo_int=`echo $ssid | awk \
|
||||
'{ \
|
||||
len=length($0); \
|
||||
@@ -289,11 +352,11 @@ getSSIDLOHI ()
|
||||
#
|
||||
updateGrub ()
|
||||
{
|
||||
grubconf=$1
|
||||
policyfile=$2
|
||||
linux=$3
|
||||
local grubconf=$1
|
||||
local policyfile=$2
|
||||
local linux=$3
|
||||
|
||||
tmpfile="/tmp/new_grub.conf"
|
||||
local tmpfile="/tmp/new_grub.conf"
|
||||
|
||||
cat $grubconf | \
|
||||
awk -vpolicy=$policyfile \
|
||||
@@ -343,7 +406,59 @@ updateGrub ()
|
||||
echo "Could not create temporary file! Aborting."
|
||||
exit -1
|
||||
fi
|
||||
mv -f $tmpfile $grubconf
|
||||
diff $tmpfile $grubconf > /dev/null
|
||||
RES=$?
|
||||
if [ "$RES" == "0" ]; then
|
||||
echo "No changes were made to $grubconf."
|
||||
else
|
||||
echo "Successfully updated $grubconf."
|
||||
mv -f $tmpfile $grubconf
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
#Compile a policy into its binary representation
|
||||
# Parameters:
|
||||
# 1st: The directory where the ./policies directory is located at
|
||||
# 2nd: The name of the policy
|
||||
genBinPolicy ()
|
||||
{
|
||||
local root=$1
|
||||
local policy=$2
|
||||
pushd $root > /dev/null
|
||||
xensec_xml2bin -d policies $policy > /dev/null
|
||||
popd > /dev/null
|
||||
}
|
||||
|
||||
|
||||
# Copy the bootpolicy into the destination directory
|
||||
# Generate the policy's .bin and .map files if necessary
|
||||
# Parameters:
|
||||
# 1st: Destination directory
|
||||
# 2nd: The root directory of the security tools; this is where the
|
||||
# policies directory is located at
|
||||
# 3rd: The policy name
|
||||
# Returns '1' on success, '0' on failure.
|
||||
cpBootPolicy ()
|
||||
{
|
||||
local dest=$1
|
||||
local root=$2
|
||||
local policy=$3
|
||||
local binfile=$root/policies/$policy/$policy.bin
|
||||
local dstfile=$dest/$policy.bin
|
||||
if [ ! -e $binfile ]; then
|
||||
genBinPolicy $root $policy
|
||||
if [ ! -e $binfile ]; then
|
||||
echo "Could not compile policy '$policy'."
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -e $dstfile -o \
|
||||
$binfile -nt $dstfile ]; then
|
||||
cp -f $binfile $dstfile
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
@@ -352,7 +467,11 @@ updateGrub ()
|
||||
# 1st: Full or relative path to the policy's mapfile
|
||||
showLabels ()
|
||||
{
|
||||
mapfile=$1
|
||||
local mapfile=$1
|
||||
local line
|
||||
local ITEM
|
||||
local found=0
|
||||
|
||||
if [ ! -r "$mapfile" -o "$mapfile" == "" ]; then
|
||||
echo "Cannot read from vm configuration file $vmfile."
|
||||
return -1
|
||||
@@ -417,8 +536,8 @@ showLabels ()
|
||||
# 2nd: the name of the policy
|
||||
getDefaultSsid ()
|
||||
{
|
||||
mapfile=$1
|
||||
pol=$2
|
||||
local mapfile=$1
|
||||
local pol=$2
|
||||
RES=`cat $mapfile \
|
||||
awk -vpol=$pol \
|
||||
{ \
|
||||
@@ -446,10 +565,13 @@ getDefaultSsid ()
|
||||
# other : Prompts the user whether to proceed
|
||||
relabel ()
|
||||
{
|
||||
vmfile=$1
|
||||
label=$2
|
||||
mapfile=$3
|
||||
mode=$4
|
||||
local vmfile=$1
|
||||
local label=$2
|
||||
local mapfile=$3
|
||||
local mode=$4
|
||||
local SSIDLO
|
||||
local SSIDHI
|
||||
local RES
|
||||
|
||||
if [ ! -r "$vmfile" ]; then
|
||||
echo "Cannot read from vm configuration file $vmfile."
|
||||
@@ -556,8 +678,8 @@ relabel ()
|
||||
fi
|
||||
|
||||
#Write the output
|
||||
vmtmp1="/tmp/__setlabel.tmp1"
|
||||
vmtmp2="/tmp/__setlabel.tmp2"
|
||||
local vmtmp1="/tmp/__setlabel.tmp1"
|
||||
local vmtmp2="/tmp/__setlabel.tmp2"
|
||||
touch $vmtmp1
|
||||
touch $vmtmp2
|
||||
if [ ! -w "$vmtmp1" -o ! -w "$vmtmp2" ]; then
|
||||
@@ -584,8 +706,10 @@ relabel ()
|
||||
# 2nd: Full or relative path to the policy's mapfile
|
||||
translateSSIDREF ()
|
||||
{
|
||||
ssidref=$1
|
||||
mapfile=$2
|
||||
local ssidref=$1
|
||||
local mapfile=$2
|
||||
local line1
|
||||
local line2
|
||||
|
||||
if [ ! -r "$mapfile" -o "$mapfile" == "" ]; then
|
||||
echo "Cannot read from vm configuration file $vmfile."
|
||||
|
||||
@@ -44,12 +44,13 @@ fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
|
||||
|
||||
void usage(char *progname)
|
||||
{
|
||||
printf("Use: %s \n"
|
||||
printf("Usage: %s ACTION\n"
|
||||
"ACTION is one of:\n"
|
||||
"\t getpolicy\n"
|
||||
"\t dumpstats\n"
|
||||
"\t loadpolicy <binary policy file>\n"
|
||||
"\t getssid -d <domainid> [-f]\n"
|
||||
"\t getssid -s <ssidref> [-f]\n", progname);
|
||||
"\t getssid -s <ssidref> [-f]\n", progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@@ -85,6 +86,7 @@ static inline int do_acm_op(int xc_handle, struct acm_op * op)
|
||||
|
||||
if ((ret = do_xen_hypercall(xc_handle, &hypercall)) < 0)
|
||||
{
|
||||
printf( "ACM operation failed: errno=%d\n", errno );
|
||||
if (errno == EACCES)
|
||||
fprintf(stderr, "ACM operation failed -- need to"
|
||||
" rebuild the user-space tool set?\n");
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* sHype policy translation tool. This tool takes an XML
|
||||
* policy specification as input and produces a binary
|
||||
* policy file that can be loaded into Xen through the
|
||||
* ACM operations (secpol_tool loadpolicy) interface or at
|
||||
* ACM operations (xensec_tool loadpolicy) interface or at
|
||||
* boot time (grub module parameter)
|
||||
*
|
||||
* indent -i4 -kr -nut
|
||||
@@ -102,12 +102,22 @@ int have_chwall = 0;
|
||||
/* input/output file names */
|
||||
char *policy_filename = NULL,
|
||||
*label_filename = NULL,
|
||||
*binary_filename = NULL, *mapping_filename = NULL;
|
||||
*binary_filename = NULL, *mapping_filename = NULL,
|
||||
*schema_filename = NULL;
|
||||
|
||||
void usage(char *prg)
|
||||
{
|
||||
printf("usage:\n%s policyname[-policy.xml/-security_label_template.xml]\n",
|
||||
prg);
|
||||
printf("Usage: %s [OPTIONS] POLICYNAME\n", prg);
|
||||
printf("POLICYNAME is the directory name within the policy directory\n");
|
||||
printf("that contains the policy files. The default policy directory\n");
|
||||
printf("is '%s' (see the '-d' option below to change it)\n", POLICY_DIR);
|
||||
printf("The policy files contained in the POLICYNAME directory must be named:\n");
|
||||
printf("\tPOLICYNAME-security_policy.xml\n");
|
||||
printf("\tPOLICYNAME-security_label_template.xml\n\n");
|
||||
printf("OPTIONS:\n");
|
||||
printf("\t-d POLICYDIR\n");
|
||||
printf("\t\tUse POLICYDIR as the policy directory. This directory must contain\n");
|
||||
printf("\t\tthe policy schema file 'security_policy.xsd'\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@@ -1237,7 +1247,7 @@ int is_valid(xmlDocPtr doc)
|
||||
xmlSchemaParserCtxtPtr schemaparser_ctxt = NULL;
|
||||
xmlSchemaValidCtxtPtr schemavalid_ctxt = NULL;
|
||||
|
||||
schemaparser_ctxt = xmlSchemaNewParserCtxt(SCHEMA_FILENAME);
|
||||
schemaparser_ctxt = xmlSchemaNewParserCtxt(schema_filename);
|
||||
schema_ctxt = xmlSchemaParse(schemaparser_ctxt);
|
||||
schemavalid_ctxt = xmlSchemaNewValidCtxt(schema_ctxt);
|
||||
|
||||
@@ -1246,12 +1256,12 @@ int is_valid(xmlDocPtr doc)
|
||||
if ((err = xmlSchemaIsValid(schemavalid_ctxt)) != 1)
|
||||
{
|
||||
printf("ERROR: Invalid schema file %s (err=%d)\n",
|
||||
SCHEMA_FILENAME, err);
|
||||
schema_filename, err);
|
||||
err = -EIO;
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
printf("XML Schema %s valid.\n", SCHEMA_FILENAME);
|
||||
printf("XML Schema %s valid.\n", schema_filename);
|
||||
#endif
|
||||
if ((err = xmlSchemaValidateDoc(schemavalid_ctxt, doc)))
|
||||
{
|
||||
@@ -1275,37 +1285,59 @@ int main(int argc, char **argv)
|
||||
char *file_prefix;
|
||||
int prefix_len;
|
||||
|
||||
int opt_char;
|
||||
char *policy_dir = POLICY_DIR;
|
||||
|
||||
if (ACM_POLICY_VERSION != WRITTEN_AGAINST_ACM_POLICY_VERSION)
|
||||
{
|
||||
printf("ERROR: This program was written against an older ACM version.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (argc != 2)
|
||||
while ((opt_char = getopt(argc, argv, "d:")) != -1) {
|
||||
switch (opt_char) {
|
||||
case 'd':
|
||||
policy_dir = malloc(strlen(optarg) + 2); // null terminator and possibly "/"
|
||||
if (!policy_dir) {
|
||||
printf("ERROR allocating directory name memory.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
strcpy(policy_dir, optarg);
|
||||
if (policy_dir[strlen(policy_dir) - 1] != '/')
|
||||
strcat(policy_dir, "/");
|
||||
break;
|
||||
|
||||
default:
|
||||
usage(basename(argv[0]));
|
||||
}
|
||||
}
|
||||
|
||||
if ((argc - optind) != 1)
|
||||
usage(basename(argv[0]));
|
||||
|
||||
prefix_len = strlen(POLICY_SUBDIR) +
|
||||
strlen(argv[1]) + 1 /* "/" */ +
|
||||
strlen(argv[1]) + 1 /* "/" */ ;
|
||||
prefix_len = strlen(policy_dir) +
|
||||
strlen(argv[optind]) + 1 /* "/" */ +
|
||||
strlen(argv[optind]) + 1 /* null terminator */ ;
|
||||
|
||||
file_prefix = malloc(prefix_len);
|
||||
policy_filename = malloc(prefix_len + strlen(POLICY_EXTENSION));
|
||||
label_filename = malloc(prefix_len + strlen(LABEL_EXTENSION));
|
||||
binary_filename = malloc(prefix_len + strlen(BINARY_EXTENSION));
|
||||
mapping_filename = malloc(prefix_len + strlen(MAPPING_EXTENSION));
|
||||
schema_filename = malloc(strlen(policy_dir) + strlen(SCHEMA_FILENAME) + 1);
|
||||
|
||||
if (!file_prefix || !policy_filename || !label_filename ||
|
||||
!binary_filename || !mapping_filename)
|
||||
!binary_filename || !mapping_filename || !schema_filename)
|
||||
{
|
||||
printf("ERROR allocating file name memory.\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
/* create input/output filenames out of prefix */
|
||||
strcat(file_prefix, POLICY_SUBDIR);
|
||||
strcat(file_prefix, argv[1]);
|
||||
strcpy(file_prefix, policy_dir);
|
||||
strcat(file_prefix, argv[optind]);
|
||||
strcat(file_prefix, "/");
|
||||
strcat(file_prefix, argv[1]);
|
||||
strcat(file_prefix, argv[optind]);
|
||||
|
||||
strcpy(policy_filename, file_prefix);
|
||||
strcpy(label_filename, file_prefix);
|
||||
@@ -1317,11 +1349,14 @@ int main(int argc, char **argv)
|
||||
strcat(binary_filename, BINARY_EXTENSION);
|
||||
strcat(mapping_filename, MAPPING_EXTENSION);
|
||||
|
||||
strcpy(schema_filename, policy_dir);
|
||||
strcat(schema_filename, SCHEMA_FILENAME);
|
||||
|
||||
labeldoc = xmlParseFile(label_filename);
|
||||
|
||||
if (labeldoc == NULL)
|
||||
{
|
||||
printf("Error: could not parse file %s.\n", argv[1]);
|
||||
printf("Error: could not parse file %s.\n", argv[optind]);
|
||||
goto out2;
|
||||
}
|
||||
|
||||
@@ -1337,7 +1372,7 @@ int main(int argc, char **argv)
|
||||
|
||||
if (policydoc == NULL)
|
||||
{
|
||||
printf("Error: could not parse file %s.\n", argv[1]);
|
||||
printf("Error: could not parse file %s.\n", argv[optind]);
|
||||
goto out1;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* License.
|
||||
*
|
||||
*/
|
||||
#define POLICY_SUBDIR "policies/"
|
||||
#define POLICY_DIR "/etc/xen/acm-security/policies/"
|
||||
#define POLICY_EXTENSION "-security_policy.xml"
|
||||
#define LABEL_EXTENSION "-security_label_template.xml"
|
||||
#define BINARY_EXTENSION ".bin"
|
||||
@@ -20,7 +20,7 @@
|
||||
#define PRIMARY_COMPONENT_ATTR_NAME "order"
|
||||
#define BOOTSTRAP_LABEL_ATTR_NAME "bootstrap"
|
||||
#define PRIMARY_COMPONENT "PrimaryPolicyComponent"
|
||||
#define SCHEMA_FILENAME "policies/security_policy.xsd"
|
||||
#define SCHEMA_FILENAME "security_policy.xsd"
|
||||
|
||||
/* basic states (used as 1 << X) */
|
||||
#define XML2BIN_SECPOL 0 /* policy tokens */
|
||||
|
||||
+35
-65
@@ -35,102 +35,72 @@ if [ -z "$runbash" ]; then
|
||||
fi
|
||||
|
||||
export PATH=$PATH:.
|
||||
source labelfuncs.sh
|
||||
dir=`dirname $0`
|
||||
source $dir/labelfuncs.sh
|
||||
|
||||
usage ()
|
||||
{
|
||||
prg=`basename $0`
|
||||
echo "Use this tool to put the ssidref corresponding to a label of a policy into
|
||||
the VM configuration file, or use it to display all labels of a policy.
|
||||
|
||||
Usage: $0 [Option] <vmfile> <label> [<policy name>]
|
||||
or $0 -l [<policy name>]
|
||||
Usage: $prg [-r] <vmfile> <label> [<policy name> [<policy dir>]] or
|
||||
$prg -l [<policy name> [<policy dir>]]
|
||||
|
||||
Valid options are:
|
||||
-r : to relabel a file without being prompted
|
||||
|
||||
-l : to show the valid labels in a map file
|
||||
vmfile : XEN vm configuration file; give complete path
|
||||
label : the label to map to an ssidref
|
||||
policy name : the name of the policy, i.e. 'chwall'
|
||||
If the policy name is omitted, it is attempted
|
||||
to find the current policy's name in grub.conf.
|
||||
|
||||
-l [<policy name>] is used to show valid labels in the map file of
|
||||
the given or current policy. If the policy name
|
||||
is omitted, it will be tried to determine the
|
||||
current policy from grub.conf (/boot/grub/grub.conf)
|
||||
|
||||
policy dir : the directory where the <policy name> policy is located
|
||||
The default location is '/etc/xen/acm-security/policies'
|
||||
"
|
||||
}
|
||||
|
||||
|
||||
if [ "$1" == "-r" ]; then
|
||||
mode="relabel"
|
||||
shift
|
||||
elif [ "$1" == "-l" ]; then
|
||||
mode="show"
|
||||
shift
|
||||
elif [ "$1" == "-?" ]; then
|
||||
elif [ "$1" == "-h" ]; then
|
||||
mode="usage"
|
||||
fi
|
||||
|
||||
if [ "$mode" == "show" ]; then
|
||||
if [ "$1" == "" ]; then
|
||||
findGrubConf
|
||||
ret=$?
|
||||
if [ $ret -eq 0 ]; then
|
||||
echo "Could not find grub.conf"
|
||||
exit -1;
|
||||
fi
|
||||
findPolicyInGrub $grubconf
|
||||
if [ "$policy" != "" ]; then
|
||||
echo "Assuming policy to be '$policy'.";
|
||||
else
|
||||
echo "Could not find policy."
|
||||
exit -1;
|
||||
fi
|
||||
else
|
||||
policy=$1;
|
||||
fi
|
||||
|
||||
|
||||
findMapFile $policy
|
||||
res=$?
|
||||
if [ "$res" != "0" ]; then
|
||||
showLabels $mapfile
|
||||
else
|
||||
echo "Could not find map file for policy '$policy'."
|
||||
fi
|
||||
elif [ "$mode" == "usage" ]; then
|
||||
if [ "$mode" == "usage" ]; then
|
||||
usage
|
||||
elif [ "$mode" == "show" ]; then
|
||||
setPolicyVars $1 $2
|
||||
ret=$?
|
||||
if [ $ret -eq 0 ]; then
|
||||
echo "Error when trying to find policy-related information."
|
||||
exit -1
|
||||
fi
|
||||
findMapFile $policy $policydir
|
||||
ret=$?
|
||||
if [ $ret -eq 0 ]; then
|
||||
echo "Could not find map file for policy '$policy'."
|
||||
exit -1
|
||||
fi
|
||||
showLabels $mapfile
|
||||
else
|
||||
if [ "$2" == "" ]; then
|
||||
usage
|
||||
exit -1
|
||||
fi
|
||||
if [ "$3" == "" ]; then
|
||||
findGrubConf
|
||||
ret=$?
|
||||
if [ $ret -eq 0 ]; then
|
||||
echo "Could not find grub.conf"
|
||||
exit -1;
|
||||
fi
|
||||
findPolicyInGrub $grubconf
|
||||
if [ "$policy" != "" ]; then
|
||||
echo "Assuming policy to be '$policy'.";
|
||||
else
|
||||
echo "Could not find policy."
|
||||
exit -1;
|
||||
fi
|
||||
|
||||
else
|
||||
policy=$3;
|
||||
setPolicyVars $3 $4
|
||||
ret=$?
|
||||
if [ $ret -eq 0 ]; then
|
||||
echo "Error when trying to find policy-related information."
|
||||
exit -1
|
||||
fi
|
||||
findMapFile $policy
|
||||
res=$?
|
||||
if [ "$res" != "0" ]; then
|
||||
relabel $1 $2 $mapfile $mode
|
||||
else
|
||||
echo "Could not find map file for policy '$3'."
|
||||
findMapFile $policy $policydir
|
||||
ret=$?
|
||||
if [ $ret -eq 0 ]; then
|
||||
echo "Could not find map file for policy '$policy'."
|
||||
exit -1
|
||||
fi
|
||||
|
||||
relabel $1 $2 $mapfile $mode
|
||||
fi
|
||||
+35
-143
@@ -22,166 +22,49 @@ if [ -z "$runbash" ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
dir=`dirname $0`
|
||||
source $dir/labelfuncs.sh
|
||||
|
||||
acmroot=$ACM_DEFAULT_ROOT
|
||||
|
||||
|
||||
# Show usage of this program
|
||||
usage ()
|
||||
{
|
||||
prg=`basename $0`
|
||||
echo "Use this tool to add the binary policy to the Xen grub entry and
|
||||
have Xen automatically enforce the policy when starting.
|
||||
|
||||
Usage: $0 <policy name> <root of xen repository>
|
||||
|
||||
<policy name> : The name of the policy, i.e. xen_null
|
||||
<root of xen repository> : The root of the XEN repository. Give
|
||||
complete path.
|
||||
Usage: $prg [-d <policies root>] <policy name> [<kernel version>]
|
||||
|
||||
<policies root> : The directory where the policies directory is located in;
|
||||
default is $acmroot
|
||||
<policy name> : The name of the policy, i.e. xen_null
|
||||
<kernel version> : The version of the kernel to apply the policy
|
||||
against, i.e. 2.6.12.6-xen0
|
||||
If not specified, a kernel version ending with '-xen0'
|
||||
will be searched for in '/lib/modules'
|
||||
"
|
||||
}
|
||||
|
||||
# This function sets the global variable 'linux'
|
||||
# to the name of the linux kernel that was compiled
|
||||
# For now a pattern should do the trick
|
||||
getLinuxVersion ()
|
||||
{
|
||||
path=$1
|
||||
linux=""
|
||||
for f in $path/linux-*-xen0 ; do
|
||||
versionfile=$f/include/linux/version.h
|
||||
if [ -r $versionfile ]; then
|
||||
lnx=`cat $versionfile | \
|
||||
grep UTS_RELEASE | \
|
||||
awk '{ \
|
||||
len=length($3); \
|
||||
version=substr($3,2,len-2); \
|
||||
split(version,numbers,"."); \
|
||||
if (numbers[4]=="") { \
|
||||
printf("%s.%s.%s", \
|
||||
numbers[1], \
|
||||
numbers[2], \
|
||||
numbers[3]); \
|
||||
} else { \
|
||||
printf("%s.%s.%s[.0-9]*-xen0",\
|
||||
numbers[1], \
|
||||
numbers[2], \
|
||||
numbers[3]); \
|
||||
} \
|
||||
}'`
|
||||
fi
|
||||
if [ "$lnx" != "" ]; then
|
||||
linux="[./0-9a-zA-z]*$lnx"
|
||||
return;
|
||||
fi
|
||||
done
|
||||
|
||||
#Last resort.
|
||||
linux="vmlinuz-2.[45678].[0-9]*[.0-9]*-xen0$"
|
||||
}
|
||||
|
||||
#Return where the grub.conf file is.
|
||||
#I only know of one place it can be.
|
||||
findGrubConf()
|
||||
{
|
||||
grubconf="/boot/grub/grub.conf"
|
||||
if [ -w $grubconf ]; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
#Update the grub configuration file.
|
||||
#Search for existing entries and replace the current
|
||||
#policy entry with the policy passed to this script
|
||||
#
|
||||
#Arguments passed to this function
|
||||
# 1st : the grub configuration file
|
||||
# 2nd : the binary policy file name
|
||||
# 3rd : the name or pattern of the linux kernel name to match
|
||||
#
|
||||
# The algorithm here is based on pattern matching
|
||||
# and is working correctly if
|
||||
# - under a title a line beginning with 'kernel' is found
|
||||
# whose following item ends with "xen.gz"
|
||||
# Example: kernel /xen.gz dom0_mem=....
|
||||
# - a module line matching the 3rd parameter is found
|
||||
#
|
||||
updateGrub ()
|
||||
{
|
||||
grubconf=$1
|
||||
policyfile=$2
|
||||
linux=$3
|
||||
if [ "$1" == "-h" ]; then
|
||||
usage
|
||||
exit 0
|
||||
elif [ "$1" == "-d" ]; then
|
||||
shift
|
||||
acmroot=$1
|
||||
shift
|
||||
fi
|
||||
|
||||
tmpfile="/tmp/new_grub.conf"
|
||||
|
||||
cat $grubconf | \
|
||||
awk -vpolicy=$policyfile \
|
||||
-vlinux=$linux '{ \
|
||||
if ( $1 == "title" ) { \
|
||||
kernelfound = 0; \
|
||||
if ( policymaycome == 1 ){ \
|
||||
printf ("\tmodule %s%s\n", path, policy); \
|
||||
} \
|
||||
policymaycome = 0; \
|
||||
} \
|
||||
else if ( $1 == "kernel" ) { \
|
||||
if ( match($2,"xen.gz$") ) { \
|
||||
path=substr($2,1,RSTART-1); \
|
||||
kernelfound = 1; \
|
||||
} \
|
||||
} \
|
||||
else if ( $1 == "module" && \
|
||||
kernelfound == 1 && \
|
||||
match($2,linux) ) { \
|
||||
policymaycome = 1; \
|
||||
} \
|
||||
else if ( $1 == "module" && \
|
||||
kernelfound == 1 && \
|
||||
policymaycome == 1 && \
|
||||
match($2,"[0-9a-zA-Z]*.bin$") ) { \
|
||||
printf ("\tmodule %s%s\n", path, policy); \
|
||||
policymaycome = 0; \
|
||||
kernelfound = 0; \
|
||||
dontprint = 1; \
|
||||
} \
|
||||
else if ( $1 == "" && \
|
||||
kernelfound == 1 && \
|
||||
policymaycome == 1) { \
|
||||
dontprint = 1; \
|
||||
} \
|
||||
if (dontprint == 0) { \
|
||||
printf ("%s\n", $0); \
|
||||
} \
|
||||
dontprint = 0; \
|
||||
} END { \
|
||||
if ( policymaycome == 1 ) { \
|
||||
printf ("\tmodule %s%s\n", path, policy); \
|
||||
} \
|
||||
}' > $tmpfile
|
||||
if [ ! -r $tmpfile ]; then
|
||||
echo "Could not create temporary file! Aborting."
|
||||
exit -1
|
||||
fi
|
||||
diff $tmpfile $grubconf > /dev/null
|
||||
RES=$?
|
||||
if [ "$RES" == "0" ]; then
|
||||
echo "No changes were made to $grubconf."
|
||||
else
|
||||
echo "Successfully updated $grubconf."
|
||||
mv -f $tmpfile $grubconf
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "$1" == "" -o "$2" == "" ]; then
|
||||
if [ "$1" == "" ]; then
|
||||
echo "Error: Not enough command line parameters."
|
||||
echo ""
|
||||
usage
|
||||
exit -1
|
||||
fi
|
||||
|
||||
if [ "$1" == "-?" ]; then
|
||||
usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
policy=$1
|
||||
policyfile=$policy.bin
|
||||
@@ -189,10 +72,19 @@ policyfile=$policy.bin
|
||||
getLinuxVersion $2
|
||||
|
||||
findGrubConf
|
||||
ERR=$?
|
||||
if [ $ERR -eq 0 ]; then
|
||||
echo "Could not find grub.conf. Aborting."
|
||||
ret=$?
|
||||
if [ $ret -eq 0 ]; then
|
||||
echo "Could not find grub.conf."
|
||||
exit -1
|
||||
elif [ $ret -eq 2 ]; then
|
||||
echo "Need to have write-access to $grubconf. Exiting."
|
||||
exit -1
|
||||
fi
|
||||
|
||||
cpBootPolicy /boot $acmroot $policy
|
||||
ret=$?
|
||||
if [ $ret -ne 1 ]; then
|
||||
echo "Error copying or generating the binary policy."
|
||||
exit -1
|
||||
fi
|
||||
updateGrub $grubconf $policyfile $linux
|
||||
@@ -52,6 +52,7 @@ AC_CONFIG_FILES([
|
||||
tests/memset/Makefile
|
||||
tests/migrate/Makefile
|
||||
tests/network-attach/Makefile
|
||||
tests/network/Makefile
|
||||
tests/pause/Makefile
|
||||
tests/reboot/Makefile
|
||||
tests/restore/Makefile
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/python
|
||||
"""
|
||||
Network.py - Common utilities for network tests
|
||||
|
||||
Copyright (C) International Business Machines Corp., 2005
|
||||
Author: Jim Dykman <dykman@us.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; 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
|
||||
|
||||
"""
|
||||
import sys;
|
||||
import os;
|
||||
import atexit;
|
||||
|
||||
from Test import *
|
||||
from Xm import *
|
||||
|
||||
class NetworkError(Exception):
|
||||
def __init__(self, msg):
|
||||
self.errMsg = msg
|
||||
|
||||
def __str__(self):
|
||||
return str(self.errMsg)
|
||||
|
||||
def undo_dom0_alias(eth, ip):
|
||||
traceCommand("ip addr del " + ip + " dev " + eth)
|
||||
|
||||
class XmNetwork:
|
||||
|
||||
def __init__(self):
|
||||
# Check for existing zeroconf address. We are using the zeroconf
|
||||
# address range as static IP addresses.... if someone is using
|
||||
# real zeroconf addresses, then we're going to skip tests to
|
||||
# avoid interfering with them.
|
||||
rc, out = traceCommand(
|
||||
"ip addr show |grep \"inet 169.254\" | grep -v vif")
|
||||
|
||||
if rc == 0:
|
||||
SKIP("Zeroconf address found: " + out)
|
||||
|
||||
def calc_ip_address(self, dom, interface):
|
||||
# Generate an IP address from the dom# and eth#:
|
||||
# 169.254.(eth#+153).(dom#+10)
|
||||
ethnum = int(interface[len("eth"):])
|
||||
domnum = int(dom[len("dom"):])
|
||||
return "169.254."+ str(ethnum+153) + "." + str(domnum+10)
|
||||
|
||||
def ip(self, dom, interface, todomname=None, toeth=None):
|
||||
newip = self.calc_ip_address(dom, interface)
|
||||
|
||||
# If the testcase is going to talk to dom0, we need to add an
|
||||
# IP address in the proper subnet
|
||||
if dom == "dom0":
|
||||
# The domain's vif is a convenient place to add to
|
||||
vifname = "vif" + str(domid(todomname)) + "." + toeth[3:]
|
||||
|
||||
# register the exit handler FIRST, just in case
|
||||
atexit.register(undo_dom0_alias, vifname, newip)
|
||||
|
||||
# add the alias
|
||||
status, output = traceCommand("ip addr add " + newip +
|
||||
" dev " + vifname)
|
||||
if status:
|
||||
SKIP("\"ip addr add\" failed")
|
||||
return newip
|
||||
|
||||
def mask(self, dom, interface):
|
||||
return "255.255.255.0"
|
||||
@@ -4,6 +4,7 @@
|
||||
#
|
||||
|
||||
from Console import *
|
||||
from Network import *
|
||||
from Test import *
|
||||
from Xm import *
|
||||
from XenDomain import *
|
||||
|
||||
@@ -13,6 +13,7 @@ SUBDIRS = \
|
||||
list \
|
||||
memmax \
|
||||
memset \
|
||||
network \
|
||||
network-attach \
|
||||
pause \
|
||||
reboot \
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright (C) International Business Machines Corp., 2005
|
||||
# Author: <dykman@us.ibm.com>
|
||||
|
||||
# Ping tests on local interfaces.
|
||||
# - creates a single guest domain
|
||||
# - sets up a single NIC
|
||||
# - conducts ping tests to the local loopback and IP address.
|
||||
|
||||
# ping -c 1 -s $size 127.0.0.1
|
||||
# ping -c 1 -s $size $local_IP
|
||||
# where $size = 1, 48, 64, 512, 1440, 1500, 1505,
|
||||
# 4096, 4192, 32767, 65507, 65508
|
||||
|
||||
pingsizes = [ 1, 48, 64, 512, 1440, 1500, 1505, 4096, 4192,
|
||||
32767, 65507 ]
|
||||
|
||||
|
||||
|
||||
from XmTestLib import *
|
||||
rc = 0
|
||||
|
||||
Net = XmNetwork()
|
||||
|
||||
# read an IP address from the config
|
||||
ip = Net.ip("dom1", "eth0")
|
||||
mask = Net.mask("dom1", "eth0")
|
||||
|
||||
# Fire up a guest domain w/1 nic
|
||||
domain = XmTestDomain(extraOpts={ 'nics' : 1 })
|
||||
try:
|
||||
domain.configSetVar('vif', " [ 'ip=" + ip + "' ]")
|
||||
domain.start()
|
||||
except DomainError, e:
|
||||
if verbose:
|
||||
print "Failed to create test domain because:"
|
||||
print e.extra
|
||||
FAIL(str(e))
|
||||
|
||||
|
||||
# Attach a console
|
||||
try:
|
||||
console = XmConsole(domain.getName(), historySaveCmds=True)
|
||||
except ConsoleError, e:
|
||||
FAIL(str(e))
|
||||
|
||||
try:
|
||||
# Activate the console
|
||||
console.sendInput("bhs")
|
||||
|
||||
# Bring up the "lo" interface.
|
||||
console.runCmd("ifconfig lo up")
|
||||
|
||||
console.runCmd("ifconfig eth0 inet "+ip+" netmask "+mask+" up")
|
||||
|
||||
# First the loopback pings
|
||||
lofails=""
|
||||
for size in pingsizes:
|
||||
out = console.runCmd("ping -q -c 1 -s " + str(size) + " 127.0.0.1")
|
||||
if out["return"]:
|
||||
lofails += " " + str(size)
|
||||
|
||||
# Next comes eth0
|
||||
eth0fails=""
|
||||
for size in pingsizes:
|
||||
out = console.runCmd("ping -q -c 1 -s " + str(size) + " " + ip)
|
||||
if out["return"]:
|
||||
eth0fails += " " + str(size)
|
||||
except ConsoleError, e:
|
||||
FAIL(str(e))
|
||||
except NetworkError, e:
|
||||
FAIL(str(e))
|
||||
|
||||
|
||||
# Tally up failures
|
||||
failures=""
|
||||
if len(lofails):
|
||||
failures += "ping loopback failed for size" + lofails + ". "
|
||||
if len(eth0fails):
|
||||
failures += "ping eth0 failed for size" + eth0fails + "."
|
||||
if len(failures):
|
||||
FAIL(failures)
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright (C) International Business Machines Corp., 2005
|
||||
# Author: <dykman@us.ibm.com>
|
||||
|
||||
# Ping tests to dom0 interface
|
||||
# - determines dom0 network
|
||||
# - creates a single guest domain
|
||||
# - sets up a single NIC on same subnet as dom0
|
||||
# - conducts ping tests to the dom0 IP address.
|
||||
|
||||
# ping -c 1 -s $size $dom0_IP
|
||||
# where $size = 1, 48, 64, 512, 1440, 1500, 1505,
|
||||
# 4096, 4192, 32767, 65507, 65508
|
||||
|
||||
pingsizes = [ 1, 48, 64, 512, 1440, 1500, 1505, 4096, 4192,
|
||||
32767, 65507 ]
|
||||
|
||||
|
||||
|
||||
from XmTestLib import *
|
||||
rc = 0
|
||||
|
||||
Net = XmNetwork()
|
||||
|
||||
try:
|
||||
# read an IP address from the config
|
||||
ip = Net.ip("dom1", "eth0")
|
||||
mask = Net.mask("dom1", "eth0")
|
||||
except NetworkError, e:
|
||||
FAIL(str(e))
|
||||
|
||||
# Fire up a guest domain w/1 nic
|
||||
domain = XmTestDomain(extraOpts={ 'nics' : 1 })
|
||||
try:
|
||||
domain.configSetVar('vif', " [ 'ip=" + ip + "' ]")
|
||||
domain.start()
|
||||
except DomainError, e:
|
||||
if verbose:
|
||||
print "Failed to create test domain because:"
|
||||
print e.extra
|
||||
FAIL(str(e))
|
||||
|
||||
|
||||
# Attach a console
|
||||
try:
|
||||
console = XmConsole(domain.getName(), historySaveCmds=True)
|
||||
# Activate the console
|
||||
console.sendInput("bhs")
|
||||
except ConsoleError, e:
|
||||
FAIL(str(e))
|
||||
|
||||
try:
|
||||
# Add a suitable dom0 IP address
|
||||
dom0ip = Net.ip("dom0", "eth0", todomname=domain.getName(), toeth="eth0")
|
||||
except NetworkError, e:
|
||||
FAIL(str(e))
|
||||
|
||||
try:
|
||||
console.runCmd("ifconfig eth0 inet "+ip+" netmask "+mask+" up")
|
||||
|
||||
# Ping dom0
|
||||
fails=""
|
||||
for size in pingsizes:
|
||||
out = console.runCmd("ping -q -c 1 -s " + str(size) + " " + dom0ip)
|
||||
if out["return"]:
|
||||
fails += " " + str(size)
|
||||
except ConsoleError, e:
|
||||
FAIL(str(e))
|
||||
|
||||
if len(fails):
|
||||
FAIL("Ping to dom0 failed for size" + fails + ".")
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright (C) International Business Machines Corp., 2005
|
||||
# Author: <dykman@us.ibm.com>
|
||||
|
||||
# Ping tests to domU interface
|
||||
# - creates two guest domains
|
||||
# - sets up a single NIC on each on same subnet
|
||||
# - conducts ping tests to the domU IP address.
|
||||
|
||||
# ping -c 1 -s $size $domU_IP
|
||||
# where $size = 1, 48, 64, 512, 1440, 1500, 1505,
|
||||
# 4096, 4192, 32767, 65507, 65508
|
||||
|
||||
pingsizes = [ 1, 48, 64, 512, 1440, 1500, 1505, 4096, 4192,
|
||||
32767, 65507 ]
|
||||
|
||||
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
|
||||
def netDomain(ip):
|
||||
dom = XmTestDomain(extraOpts={ 'nics' : 1 })
|
||||
try:
|
||||
dom.configSetVar('vif', " [ 'ip=" + ip + "' ]")
|
||||
dom.start()
|
||||
except DomainError, e:
|
||||
if verbose:
|
||||
print "Failed to create test domain because:"
|
||||
print e.extra
|
||||
FAIL(str(e))
|
||||
try:
|
||||
# Attach a console
|
||||
console = XmConsole(dom.getName(), historySaveCmds=True)
|
||||
# Activate the console
|
||||
console.sendInput("bhs")
|
||||
except ConsoleError, e:
|
||||
FAIL(str(e))
|
||||
return console
|
||||
|
||||
rc = 0
|
||||
|
||||
Net = XmNetwork()
|
||||
|
||||
try:
|
||||
# pick an IP address
|
||||
ip1 = Net.ip("dom1", "eth2")
|
||||
mask1 = Net.mask("dom1", "eth2")
|
||||
except NetworkError, e:
|
||||
FAIL(str(e))
|
||||
|
||||
try:
|
||||
# pick another IP address
|
||||
ip2 = Net.ip("dom2", "eth2")
|
||||
mask2 = Net.mask("dom2", "eth2")
|
||||
except NetworkError, e:
|
||||
FAIL(str(e))
|
||||
|
||||
# Fire up a pair of guest domains w/1 nic each
|
||||
pinger_console = netDomain(ip1)
|
||||
victim_console = netDomain(ip2)
|
||||
|
||||
try:
|
||||
pinger_console.runCmd("ifconfig eth0 inet "+ip1+" netmask "+mask1+" up")
|
||||
victim_console.runCmd("ifconfig eth0 inet "+ip2+" netmask "+mask2+" up")
|
||||
|
||||
# Ping the victim over eth0
|
||||
fails=""
|
||||
for size in pingsizes:
|
||||
out = pinger_console.runCmd("ping -q -c 1 -s " + str(size) + " " + ip2)
|
||||
if out["return"]:
|
||||
fails += " " + str(size)
|
||||
except ConsoleError, e:
|
||||
FAIL(str(e))
|
||||
|
||||
if len(fails):
|
||||
FAIL("Ping failed for size" + fails + ".")
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
SUBDIRS =
|
||||
|
||||
TESTS = \
|
||||
02_network_local_ping_pos.test \
|
||||
05_network_dom0_ping_pos.test \
|
||||
11_network_domU_ping_pos.test
|
||||
|
||||
|
||||
|
||||
XFAIL_TESTS = \
|
||||
02_network_local_ping_pos.test \
|
||||
05_network_dom0_ping_pos.test \
|
||||
11_network_domU_ping_pos.test
|
||||
|
||||
EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
|
||||
|
||||
TESTS_ENVIRONMENT=@TENV@
|
||||
|
||||
%.test: %.py
|
||||
cp $< $@
|
||||
chmod +x $@
|
||||
|
||||
clean-local: am_config_clean-local
|
||||
|
||||
am_config_clean-local:
|
||||
rm -f *test
|
||||
rm -f *log
|
||||
rm -f *~
|
||||