aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@hp.com>2007-07-10 08:39:26 -0600
committerAlex Williamson <alex.williamson@hp.com>2007-07-10 08:39:26 -0600
commit2cae8465aca8f3212553e9058736ff4e9a999bc8 (patch)
tree28cc3b2fcee2c9936733f85ceec5a60ccfb3f121 /tools
parent44381fddd31c0e3b5e6b702ecf6d966ce41eaff1 (diff)
parent5410c0334235d064ceeca5f33cc0fc098d547aeb (diff)
downloadxen-2cae8465aca8f3212553e9058736ff4e9a999bc8.tar.gz
xen-2cae8465aca8f3212553e9058736ff4e9a999bc8.tar.bz2
xen-2cae8465aca8f3212553e9058736ff4e9a999bc8.zip
merge with xen-unstable.hg
Diffstat (limited to 'tools')
-rw-r--r--tools/blktap/drivers/Makefile1
-rw-r--r--tools/blktap/lib/Makefile2
-rw-r--r--tools/examples/init.d/xendomains29
-rw-r--r--tools/examples/xend-config.sxp6
-rw-r--r--tools/firmware/etherboot/README5
-rw-r--r--tools/firmware/etherboot/eb-rtl8139.zrombin32768 -> 32768 bytes
-rw-r--r--tools/firmware/rombios/rombios.c4
-rw-r--r--tools/firmware/vmxassist/vm86.c180
-rw-r--r--tools/ioemu/keymaps/ja1
-rw-r--r--tools/ioemu/keymaps/modifiers4
-rw-r--r--tools/ioemu/vnc_keysym.h4
-rw-r--r--tools/libxc/Makefile1
-rw-r--r--tools/libxc/xc_domain.c1
-rw-r--r--tools/libxc/xc_misc.c2
-rw-r--r--tools/libxc/xenctrl.h3
-rw-r--r--tools/python/xen/lowlevel/xc/xc.c69
-rw-r--r--tools/python/xen/util/acmpolicy.py1199
-rw-r--r--tools/python/xen/util/bootloader.py521
-rw-r--r--tools/python/xen/util/security.py779
-rw-r--r--tools/python/xen/util/xsconstants.py104
-rw-r--r--tools/python/xen/util/xspolicy.py66
-rw-r--r--tools/python/xen/xend/XendAPI.py66
-rw-r--r--tools/python/xen/xend/XendConfig.py40
-rw-r--r--tools/python/xen/xend/XendDomain.py35
-rw-r--r--tools/python/xen/xend/XendDomainInfo.py198
-rw-r--r--tools/python/xen/xend/XendError.py18
-rw-r--r--tools/python/xen/xend/XendNode.py61
-rw-r--r--tools/python/xen/xend/XendOptions.py3
-rw-r--r--tools/python/xen/xend/XendVDI.py12
-rw-r--r--tools/python/xen/xend/XendXSPolicy.py222
-rw-r--r--tools/python/xen/xend/XendXSPolicyAdmin.py314
-rw-r--r--tools/python/xen/xend/server/SrvDomain.py3
-rw-r--r--tools/python/xen/xend/server/blkif.py15
-rw-r--r--tools/python/xen/xend/server/netif.py9
-rw-r--r--tools/python/xen/xend/server/vfbif.py5
-rw-r--r--tools/python/xen/xm/create.py8
-rw-r--r--tools/python/xen/xm/main.py42
-rw-r--r--tools/security/policies/security_policy.xsd29
-rw-r--r--tools/security/xensec_ezpolicy16
-rw-r--r--tools/xcutils/Makefile2
-rw-r--r--tools/xenmon/xenbaked.c2
-rw-r--r--tools/xenstat/libxenstat/src/xenstat.c2
-rw-r--r--tools/xenstore/Makefile94
-rw-r--r--tools/xenstore/fake_libxc.c143
-rw-r--r--tools/xenstore/speedtest.c130
-rw-r--r--tools/xenstore/testsuite/01simple.test4
-rw-r--r--tools/xenstore/testsuite/02directory.test45
-rw-r--r--tools/xenstore/testsuite/03write.test28
-rw-r--r--tools/xenstore/testsuite/04rm.test20
-rw-r--r--tools/xenstore/testsuite/05filepermissions.test81
-rw-r--r--tools/xenstore/testsuite/06dirpermissions.test119
-rw-r--r--tools/xenstore/testsuite/07watch.test176
-rw-r--r--tools/xenstore/testsuite/08transaction.slowtest43
-rw-r--r--tools/xenstore/testsuite/08transaction.test92
-rw-r--r--tools/xenstore/testsuite/09domain.test19
-rw-r--r--tools/xenstore/testsuite/10domain-homedir.test18
-rw-r--r--tools/xenstore/testsuite/11domain-watch.test50
-rw-r--r--tools/xenstore/testsuite/12readonly.test38
-rw-r--r--tools/xenstore/testsuite/13watch-ack.test21
-rw-r--r--tools/xenstore/testsuite/14complexperms.test68
-rwxr-xr-xtools/xenstore/testsuite/test.sh64
-rw-r--r--tools/xenstore/testsuite/vg-suppressions9
-rw-r--r--tools/xenstore/xenstored_core.c105
-rw-r--r--tools/xenstore/xenstored_domain.c4
-rw-r--r--tools/xenstore/xenstored_test.h37
-rw-r--r--tools/xenstore/xenstored_transaction.c1
-rw-r--r--tools/xenstore/xenstored_watch.c12
-rw-r--r--tools/xenstore/xs_crashme.c393
-rw-r--r--tools/xenstore/xs_random.c1590
-rw-r--r--tools/xenstore/xs_stress.c207
-rw-r--r--tools/xenstore/xs_test.c812
-rw-r--r--tools/xentrace/xentrace.c2
-rw-r--r--tools/xm-test/tests/info/02_info_compiledata_pos.py4
73 files changed, 3754 insertions, 4758 deletions
diff --git a/tools/blktap/drivers/Makefile b/tools/blktap/drivers/Makefile
index c077c7221e..fca48b6ced 100644
--- a/tools/blktap/drivers/Makefile
+++ b/tools/blktap/drivers/Makefile
@@ -10,7 +10,6 @@ LIBAIO_DIR = ../../libaio/src
CFLAGS += -Werror
CFLAGS += -Wno-unused
-CFLAGS += -fno-strict-aliasing
CFLAGS += -I $(XEN_LIBXC) -I $(LIBAIO_DIR)
CFLAGS += $(INCLUDES) -I. -I../../xenstore
CFLAGS += -D_GNU_SOURCE
diff --git a/tools/blktap/lib/Makefile b/tools/blktap/lib/Makefile
index 833887ade0..f5621e1e23 100644
--- a/tools/blktap/lib/Makefile
+++ b/tools/blktap/lib/Makefile
@@ -16,7 +16,7 @@ SRCS += xenbus.c blkif.c xs_api.c
CFLAGS += -Werror
CFLAGS += -Wno-unused
-CFLAGS += -fno-strict-aliasing -fPIC
+CFLAGS += -fPIC
# get asprintf():
CFLAGS += -D _GNU_SOURCE
diff --git a/tools/examples/init.d/xendomains b/tools/examples/init.d/xendomains
index 0fffd42c80..987f994a4f 100644
--- a/tools/examples/init.d/xendomains
+++ b/tools/examples/init.d/xendomains
@@ -221,22 +221,26 @@ start()
if [ "$XENDOMAINS_RESTORE" = "true" ] &&
contains_something "$XENDOMAINS_SAVE"
then
- XENDOMAINS_SAVED=`/bin/ls $XENDOMAINS_SAVE/* | grep -v 'lost+found'`
mkdir -p $(dirname "$LOCKFILE")
touch $LOCKFILE
echo -n "Restoring Xen domains:"
saved_domains=`ls $XENDOMAINS_SAVE`
- for dom in $XENDOMAINS_SAVED; do
- echo -n " ${dom##*/}"
- xm restore $dom
- if [ $? -ne 0 ]; then
- rc_failed $?
- echo -n '!'
- else
- # mv $dom ${dom%/*}/.${dom##*/}
- rm $dom
- fi
- done
+ for dom in $XENDOMAINS_SAVE/*; do
+ if [ -f $dom ] ; then
+ HEADER=`head -c 16 $dom | head -n 1 2> /dev/null`
+ if [ $HEADER = "LinuxGuestRecord" ]; then
+ echo -n " ${dom##*/}"
+ xm restore $dom
+ if [ $? -ne 0 ]; then
+ rc_failed $?
+ echo -n '!'
+ else
+ # mv $dom ${dom%/*}/.${dom##*/}
+ rm $dom
+ fi
+ fi
+ fi
+ done
echo .
fi
@@ -260,7 +264,6 @@ start()
if [ $? -eq 0 ] || is_running $dom; then
echo -n "(skip)"
else
- echo "(booting)"
xm create --quiet --defconfig $dom
if [ $? -ne 0 ]; then
rc_failed $?
diff --git a/tools/examples/xend-config.sxp b/tools/examples/xend-config.sxp
index aaddbee076..adbb9e6b69 100644
--- a/tools/examples/xend-config.sxp
+++ b/tools/examples/xend-config.sxp
@@ -191,3 +191,9 @@
# The default password for VNC console on HVM domain.
# Empty string is no authentication.
(vncpasswd '')
+
+# The default keymap to use for the VM's virtual keyboard
+# when not specififed in VM's configuration
+#(keymap 'en-us')
+
+
diff --git a/tools/firmware/etherboot/README b/tools/firmware/etherboot/README
index c520699b5c..c2d4eca067 100644
--- a/tools/firmware/etherboot/README
+++ b/tools/firmware/etherboot/README
@@ -1,7 +1,8 @@
This is an Etherboot option ROM for the rtl8139 NIC. It has a few
-non-standard settings, just to do with timeouts and when to give up.
+non-standard settings, most to do with timeouts and when to give up,
+and for stricter DHCP spec compliance.
Rom-o-matic.net will provide this image at the following URL:
-http://rom-o-matic.net/5.4.2/build.php?version=5.4.2&F=ignore&nic=rtl8139%3Artl8139+--+%5B0x10ec%2C0x8139%5D&ofmt=Binary+ROM+Image%28.zrom%29&arch=i386&ASK_BOOT=-1&BOOT_FIRST=BOOT_NIC&BOOT_SECOND=BOOT_NOTHING&BOOT_THIRD=BOOT_NOTHING&BOOT_INDEX=0&STATIC_CLIENT_IP=&STATIC_SUBNET_MASK=&STATIC_SERVER_IP=&STATIC_GATEWAY_IP=&STATIC_BOOTFILE=&EXIT_ON_FILE_LOAD_ERROR=on&DHCP_CLIENT_ID=&DHCP_CLIENT_ID_LEN=&DHCP_CLIENT_ID_TYPE=&DHCP_USER_CLASS=&DHCP_USER_CLASS_LEN=&ALLOW_ONLY_ENCAPSULATED=on&DEFAULT_BOOTFILE=&CONGESTED=on&BACKOFF_LIMIT=7&TIMEOUT=180&TRY_FLOPPY_FIRST=0&EXIT_IF_NO_OFFER=on&TAGGED_IMAGE=on&ELF_IMAGE=on&PXE_IMAGE=on&DOWNLOAD_PROTO_TFTP=on&COMCONSOLE=0x3F8&CONSPEED=9600&COMPARM=0x03&PXE_EXPORT=on&CONFIG_PCI=on&CONFIG_ISA=on&BUILD_ID=&PCBIOS=on&A=Get+ROM
+http://rom-o-matic.net/5.4.3/build.php?version=5.4.3&F=ignore&nic=rtl8139%3Artl8139+--+%5B0x10ec%2C0x8139%5D&ofmt=Binary+ROM+Image%28.zrom%29&arch=i386&ASK_BOOT=-1&BOOT_FIRST=BOOT_NIC&BOOT_SECOND=BOOT_NOTHING&BOOT_THIRD=BOOT_NOTHING&BOOT_INDEX=0&STATIC_CLIENT_IP=&STATIC_SUBNET_MASK=&STATIC_SERVER_IP=&STATIC_GATEWAY_IP=&STATIC_BOOTFILE=&EXIT_ON_FILE_LOAD_ERROR=on&DHCP_CLIENT_ID=&DHCP_CLIENT_ID_LEN=&DHCP_CLIENT_ID_TYPE=&DHCP_USER_CLASS=&DHCP_USER_CLASS_LEN=&ALLOW_ONLY_ENCAPSULATED=on&DEFAULT_BOOTFILE=&CONGESTED=on&BACKOFF_LIMIT=7&TIMEOUT=180&TRY_FLOPPY_FIRST=0&EXIT_IF_NO_OFFER=on&TAGGED_IMAGE=on&ELF_IMAGE=on&PXE_IMAGE=on&DOWNLOAD_PROTO_TFTP=on&COMCONSOLE=0x3F8&CONSPEED=9600&COMPARM=0x03&PXE_EXPORT=on&CONFIG_PCI=on&CONFIG_ISA=on&BUILD_ID=&PCBIOS=on&PXE_DHCP_STRICT=on&A=Get+ROM
diff --git a/tools/firmware/etherboot/eb-rtl8139.zrom b/tools/firmware/etherboot/eb-rtl8139.zrom
index 446b55fc57..42291f4a9d 100644
--- a/tools/firmware/etherboot/eb-rtl8139.zrom
+++ b/tools/firmware/etherboot/eb-rtl8139.zrom
Binary files differ
diff --git a/tools/firmware/rombios/rombios.c b/tools/firmware/rombios/rombios.c
index c0ce1f9981..49f5afdb08 100644
--- a/tools/firmware/rombios/rombios.c
+++ b/tools/firmware/rombios/rombios.c
@@ -4675,6 +4675,10 @@ int09_function(DI, SI, BP, SP, BX, DX, CX, AX)
write_byte(0x0040, 0x18, mf2_flags);
break;
+ case 0x53: /* Del */
+ if ((shift_flags & 0x0c) == 0x0c) /* Ctrl + Alt */
+ machine_reset();
+ /* Fall through */
default:
if (scancode & 0x80) return; /* toss key releases ... */
if (scancode > MAX_SCAN_CODE) {
diff --git a/tools/firmware/vmxassist/vm86.c b/tools/firmware/vmxassist/vm86.c
index 847b625e07..0ac9ed51df 100644
--- a/tools/firmware/vmxassist/vm86.c
+++ b/tools/firmware/vmxassist/vm86.c
@@ -594,16 +594,24 @@ movr(struct regs *regs, unsigned prefix, unsigned opc)
TRACE((regs, regs->eip - eip,
"movb %%e%s, *0x%x", rnames[r], addr));
write8(addr, val);
- break;
+ return 1;
case 0x8A: /* addr32 mov r/m8, r8 */
TRACE((regs, regs->eip - eip,
"movb *0x%x, %%%s", addr, rnames[r]));
setreg8(regs, r, read8(addr));
- break;
+ return 1;
case 0x89: /* addr32 mov r16, r/m16 */
val = getreg32(regs, r);
+ if ((modrm & 0xC0) == 0xC0) {
+ if (prefix & DATA32)
+ setreg32(regs, modrm & 7, val);
+ else
+ setreg16(regs, modrm & 7, MASK16(val));
+ return 1;
+ }
+
if (prefix & DATA32) {
TRACE((regs, regs->eip - eip,
"movl %%e%s, *0x%x", rnames[r], addr));
@@ -613,9 +621,17 @@ movr(struct regs *regs, unsigned prefix, unsigned opc)
"movw %%%s, *0x%x", rnames[r], addr));
write16(addr, MASK16(val));
}
- break;
+ return 1;
+
+ case 0x8B: /* mov r/m16, r16 */
+ if ((modrm & 0xC0) == 0xC0) {
+ if (prefix & DATA32)
+ setreg32(regs, r, addr);
+ else
+ setreg16(regs, r, MASK16(addr));
+ return 1;
+ }
- case 0x8B: /* addr32 mov r/m16, r16 */
if (prefix & DATA32) {
TRACE((regs, regs->eip - eip,
"movl *0x%x, %%e%s", addr, rnames[r]));
@@ -625,7 +641,7 @@ movr(struct regs *regs, unsigned prefix, unsigned opc)
"movw *0x%x, %%%s", addr, rnames[r]));
setreg16(regs, r, read16(addr));
}
- break;
+ return 1;
case 0xC6: /* addr32 movb $imm, r/m8 */
if ((modrm >> 3) & 7)
@@ -634,9 +650,9 @@ movr(struct regs *regs, unsigned prefix, unsigned opc)
write8(addr, val);
TRACE((regs, regs->eip - eip, "movb $0x%x, *0x%x",
val, addr));
- break;
+ return 1;
}
- return 1;
+ return 0;
}
/*
@@ -816,8 +832,8 @@ mov_to_seg(struct regs *regs, unsigned prefix, unsigned opc)
* 1) real->protected mode.
* 2) protected->real mode.
*/
- if ((mode != VM86_REAL_TO_PROTECTED) &&
- (mode != VM86_PROTECTED_TO_REAL))
+ if (mode != VM86_REAL_TO_PROTECTED &&
+ mode != VM86_PROTECTED_TO_REAL)
return 0;
/* Register source only. */
@@ -1037,8 +1053,8 @@ set_mode(struct regs *regs, enum vm86_mode newmode)
{
switch (newmode) {
case VM86_REAL:
- if ((mode == VM86_PROTECTED_TO_REAL) ||
- (mode == VM86_REAL_TO_PROTECTED)) {
+ if (mode == VM86_PROTECTED_TO_REAL ||
+ mode == VM86_REAL_TO_PROTECTED) {
regs->eflags &= ~EFLAGS_TF;
real_mode(regs);
} else if (mode != VM86_REAL)
@@ -1121,7 +1137,7 @@ jmpl_indirect(struct regs *regs, int prefix, unsigned modrm)
if (mode == VM86_REAL_TO_PROTECTED) /* jump to protected mode */
set_mode(regs, VM86_PROTECTED);
- else if (mode == VM86_PROTECTED_TO_REAL)/* jump to real mode */
+ else if (mode == VM86_PROTECTED_TO_REAL) /* jump to real mode */
set_mode(regs, VM86_REAL);
else
panic("jmpl");
@@ -1147,7 +1163,7 @@ retl(struct regs *regs, int prefix)
if (mode == VM86_REAL_TO_PROTECTED) /* jump to protected mode */
set_mode(regs, VM86_PROTECTED);
- else if (mode == VM86_PROTECTED_TO_REAL)/* jump to real mode */
+ else if (mode == VM86_PROTECTED_TO_REAL) /* jump to real mode */
set_mode(regs, VM86_REAL);
else
panic("retl");
@@ -1382,9 +1398,7 @@ opcode(struct regs *regs)
case 0x39: /* addr32 cmp r16, r/m16 */
case 0x3B: /* addr32 cmp r/m16, r16 */
- if (mode != VM86_REAL && mode != VM86_REAL_TO_PROTECTED)
- goto invalid;
- if ((prefix & ADDR32) == 0)
+ if (mode == VM86_PROTECTED_TO_REAL || !(prefix & ADDR32))
goto invalid;
if (!cmp(regs, prefix, opc))
goto invalid;
@@ -1427,37 +1441,17 @@ opcode(struct regs *regs)
}
continue;
- case 0x88: /* mov r8, r/m8 */
- case 0x8A: /* mov r/m8, r8 */
- if (mode != VM86_REAL && mode != VM86_REAL_TO_PROTECTED)
- goto invalid;
- if ((prefix & ADDR32) == 0)
+ case 0x88: /* addr32 mov r8, r/m8 */
+ case 0x8A: /* addr32 mov r/m8, r8 */
+ if (mode == VM86_PROTECTED_TO_REAL || !(prefix & ADDR32))
goto invalid;
if (!movr(regs, prefix, opc))
goto invalid;
return OPC_EMULATED;
- case 0x89: /* addr32 mov r16, r/m16 */
- if (mode == VM86_PROTECTED_TO_REAL) {
- unsigned modrm = fetch8(regs);
- unsigned addr = operand(prefix, regs, modrm);
- unsigned val, r = (modrm >> 3) & 7;
-
- if (prefix & DATA32) {
- val = getreg16(regs, r);
- write32(addr, val);
- } else {
- val = getreg32(regs, r);
- write16(addr, MASK16(val));
- }
- TRACE((regs, regs->eip - eip,
- "mov %%%s, *0x%x", rnames[r], addr));
- return OPC_EMULATED;
- }
- case 0x8B: /* addr32 mov r/m16, r16 */
- if (mode != VM86_REAL && mode != VM86_REAL_TO_PROTECTED)
- goto invalid;
- if ((prefix & ADDR32) == 0)
+ case 0x89: /* mov r16, r/m16 */
+ case 0x8B: /* mov r/m16, r16 */
+ if (mode != VM86_PROTECTED_TO_REAL && !(prefix & ADDR32))
goto invalid;
if (!movr(regs, prefix, opc))
goto invalid;
@@ -1469,7 +1463,7 @@ opcode(struct regs *regs)
return OPC_EMULATED;
case 0x8F: /* addr32 pop r/m16 */
- if ((prefix & ADDR32) == 0)
+ if (!(prefix & ADDR32))
goto invalid;
if (!pop(regs, prefix, opc))
goto invalid;
@@ -1498,48 +1492,48 @@ opcode(struct regs *regs)
return OPC_EMULATED;
case 0xA1: /* mov ax, r/m16 */
- {
- int addr, data;
- int seg = segment(prefix, regs, regs->vds);
- int offset = prefix & ADDR32? fetch32(regs) : fetch16(regs);
-
- if (prefix & DATA32) {
- addr = address(regs, seg, offset);
- data = read32(addr);
- setreg32(regs, 0, data);
- } else {
- addr = address(regs, seg, offset);
- data = read16(addr);
- setreg16(regs, 0, data);
- }
- TRACE((regs, regs->eip - eip, "mov *0x%x, %%ax", addr));
+ {
+ int addr, data;
+ int seg = segment(prefix, regs, regs->vds);
+ int offset = prefix & ADDR32 ? fetch32(regs) : fetch16(regs);
+
+ if (prefix & DATA32) {
+ addr = address(regs, seg, offset);
+ data = read32(addr);
+ setreg32(regs, 0, data);
+ } else {
+ addr = address(regs, seg, offset);
+ data = read16(addr);
+ setreg16(regs, 0, data);
}
+ TRACE((regs, regs->eip - eip, "mov *0x%x, %%ax", addr));
return OPC_EMULATED;
+ }
case 0xBB: /* mov bx, imm16 */
- {
- int data;
- if (prefix & DATA32) {
- data = fetch32(regs);
- setreg32(regs, 3, data);
- } else {
- data = fetch16(regs);
- setreg16(regs, 3, data);
- }
- TRACE((regs, regs->eip - eip, "mov $0x%x, %%bx", data));
+ {
+ int data;
+ if (prefix & DATA32) {
+ data = fetch32(regs);
+ setreg32(regs, 3, data);
+ } else {
+ data = fetch16(regs);
+ setreg16(regs, 3, data);
}
+ TRACE((regs, regs->eip - eip, "mov $0x%x, %%bx", data));
return OPC_EMULATED;
+ }
case 0xC6: /* addr32 movb $imm, r/m8 */
- if ((prefix & ADDR32) == 0)
+ if (!(prefix & ADDR32))
goto invalid;
if (!movr(regs, prefix, opc))
goto invalid;
return OPC_EMULATED;
case 0xCB: /* retl */
- if ((mode == VM86_REAL_TO_PROTECTED) ||
- (mode == VM86_PROTECTED_TO_REAL)) {
+ if (mode == VM86_REAL_TO_PROTECTED ||
+ mode == VM86_PROTECTED_TO_REAL) {
retl(regs, prefix);
return OPC_INVALID;
}
@@ -1576,37 +1570,37 @@ opcode(struct regs *regs)
return OPC_EMULATED;
case 0xEA: /* jmpl */
- if ((mode == VM86_REAL_TO_PROTECTED) ||
- (mode == VM86_PROTECTED_TO_REAL)) {
+ if (mode == VM86_REAL_TO_PROTECTED ||
+ mode == VM86_PROTECTED_TO_REAL) {
jmpl(regs, prefix);
return OPC_INVALID;
}
goto invalid;
- case 0xFF: /* jmpl (indirect) */
- {
- unsigned modrm = fetch8(regs);
- switch((modrm >> 3) & 7) {
- case 5: /* jmpl (indirect) */
- if ((mode == VM86_REAL_TO_PROTECTED) ||
- (mode == VM86_PROTECTED_TO_REAL)) {
- jmpl_indirect(regs, prefix, modrm);
- return OPC_INVALID;
- }
- goto invalid;
+ case 0xFF:
+ {
+ unsigned modrm = fetch8(regs);
+ switch((modrm >> 3) & 7) {
+ case 5: /* jmpl (indirect) */
+ if (mode == VM86_REAL_TO_PROTECTED ||
+ mode == VM86_PROTECTED_TO_REAL) {
+ jmpl_indirect(regs, prefix, modrm);
+ return OPC_INVALID;
+ }
+ goto invalid;
- case 6: /* push r/m16 */
- pushrm(regs, prefix, modrm);
- return OPC_EMULATED;
+ case 6: /* push r/m16 */
+ pushrm(regs, prefix, modrm);
+ return OPC_EMULATED;
- default:
- goto invalid;
- }
+ default:
+ goto invalid;
}
+ }
case 0xEB: /* short jump */
- if ((mode == VM86_REAL_TO_PROTECTED) ||
- (mode == VM86_PROTECTED_TO_REAL)) {
+ if (mode == VM86_REAL_TO_PROTECTED ||
+ mode == VM86_PROTECTED_TO_REAL) {
disp = (char) fetch8(regs);
TRACE((regs, 2, "jmp 0x%x", regs->eip + disp));
regs->eip += disp;
@@ -1629,7 +1623,7 @@ opcode(struct regs *regs)
continue;
case 0xF6: /* addr32 testb $imm, r/m8 */
- if ((prefix & ADDR32) == 0)
+ if (!(prefix & ADDR32))
goto invalid;
if (!test(regs, prefix, opc))
goto invalid;
diff --git a/tools/ioemu/keymaps/ja b/tools/ioemu/keymaps/ja
index 6947cb124c..9d90a78c81 100644
--- a/tools/ioemu/keymaps/ja
+++ b/tools/ioemu/keymaps/ja
@@ -101,6 +101,7 @@ yen 0x7d
bar 0x7d shift
underscore 0x73 shift
Henkan_Mode 0x79
+Katakana_Real 0x70
Katakana 0x70
Muhenkan 0x7b
Henkan_Mode_Real 0x79
diff --git a/tools/ioemu/keymaps/modifiers b/tools/ioemu/keymaps/modifiers
index df8a2122c3..ad35a90f7c 100644
--- a/tools/ioemu/keymaps/modifiers
+++ b/tools/ioemu/keymaps/modifiers
@@ -11,8 +11,8 @@ Control_L 0x1d
# Translate Super to Windows keys.
# This is hardcoded. See documentation for details.
-Super_R 0xdb
-Super_L 0xdc
+Super_R 0xdc
+Super_L 0xdb
# Translate Menu to the Windows Application key.
Menu 0xdd
diff --git a/tools/ioemu/vnc_keysym.h b/tools/ioemu/vnc_keysym.h
index d0d405a5ce..ea9e330f1a 100644
--- a/tools/ioemu/vnc_keysym.h
+++ b/tools/ioemu/vnc_keysym.h
@@ -290,12 +290,14 @@ static name2keysym_t name2keysym[]={
/* localized keys */
{"BackApostrophe", 0xff21},
{"Muhenkan", 0xff22},
-{"Katakana", 0xff25},
+{"Katakana", 0xff27},
{"Hankaku", 0xff29},
{"Zenkaku_Hankaku", 0xff2a},
{"Henkan_Mode_Real", 0xff23},
{"Henkan_Mode_Ultra", 0xff3e},
{"backslash_ja", 0xffa5},
+{"Katakana_Real", 0xff25},
+{"Eisu_toggle", 0xff30},
/* dead keys */
{"dead_grave", 0xfe50},
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index ddf99ed684..102653ff95 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -57,7 +57,6 @@ GUEST_SRCS-$(CONFIG_POWERPC) += xc_dom_powerpc.c
-include $(XEN_TARGET_ARCH)/Makefile
CFLAGS += -Werror -Wmissing-prototypes
-CFLAGS += -fno-strict-aliasing
CFLAGS += $(INCLUDES) -I. -I../xenstore
# Needed for posix_fadvise64() in xc_linux.c
diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
index c63135e32e..2f80b665ed 100644
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -181,6 +181,7 @@ int xc_domain_getinfo(int xc_handle,
info->blocked = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_blocked);
info->running = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_running);
info->hvm = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_hvm_guest);
+ info->debugged = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_debugged);
info->shutdown_reason =
(domctl.u.getdomaininfo.flags>>XEN_DOMINF_shutdownshift) &
diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c
index 85f7921e77..13fa65ff18 100644
--- a/tools/libxc/xc_misc.c
+++ b/tools/libxc/xc_misc.c
@@ -60,6 +60,8 @@ int xc_physinfo(int xc_handle,
sysctl.cmd = XEN_SYSCTL_physinfo;
+ memcpy(&sysctl.u.physinfo, put_info, sizeof(*put_info));
+
if ( (ret = do_sysctl(xc_handle, &sysctl)) != 0 )
return ret;
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
index e07b21e2e6..d6dc4d980f 100644
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -153,7 +153,7 @@ typedef struct xc_dominfo {
uint32_t ssidref;
unsigned int dying:1, crashed:1, shutdown:1,
paused:1, blocked:1, running:1,
- hvm:1;
+ hvm:1, debugged:1;
unsigned int shutdown_reason; /* only meaningful if shutdown==1 */
unsigned long nr_pages;
unsigned long shared_info_frame;
@@ -485,6 +485,7 @@ int xc_readconsolering(int xc_handle,
int xc_send_debug_keys(int xc_handle, char *keys);
typedef xen_sysctl_physinfo_t xc_physinfo_t;
+typedef uint32_t xc_cpu_to_node_t;
int xc_physinfo(int xc_handle,
xc_physinfo_t *info);
diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
index afe5d19c27..021d7f2a7a 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -680,33 +680,62 @@ static PyObject *pyxc_pages_to_kib(XcObject *self, PyObject *args)
static PyObject *pyxc_physinfo(XcObject *self)
{
+#define MAX_CPU_ID 255
xc_physinfo_t info;
char cpu_cap[128], *p=cpu_cap, *q=cpu_cap;
- int i;
-
+ int i, j, max_cpu_id;
+ PyObject *ret_obj, *node_to_cpu_obj;
+ xc_cpu_to_node_t map[MAX_CPU_ID];
+
+ set_xen_guest_handle(info.cpu_to_node, map);
+ info.max_cpu_id = MAX_CPU_ID;
+
if ( xc_physinfo(self->xc_handle, &info) != 0 )
return pyxc_error_to_exception();
- *q=0;
- for(i=0;i<sizeof(info.hw_cap)/4;i++)
+ *q = 0;
+ for ( i = 0; i < sizeof(info.hw_cap)/4; i++ )
{
- p+=sprintf(p,"%08x:",info.hw_cap[i]);
- if(info.hw_cap[i])
- q=p;
+ p += sprintf(p, "%08x:", info.hw_cap[i]);
+ if ( info.hw_cap[i] )
+ q = p;
}
- if(q>cpu_cap)
- *(q-1)=0;
-
- return Py_BuildValue("{s:i,s:i,s:i,s:i,s:l,s:l,s:l,s:i,s:s}",
- "threads_per_core", info.threads_per_core,
- "cores_per_socket", info.cores_per_socket,
- "sockets_per_node", info.sockets_per_node,
- "nr_nodes", info.nr_nodes,
- "total_memory", pages_to_kib(info.total_pages),
- "free_memory", pages_to_kib(info.free_pages),
- "scrub_memory", pages_to_kib(info.scrub_pages),
- "cpu_khz", info.cpu_khz,
- "hw_caps", cpu_cap);
+ if ( q > cpu_cap )
+ *(q-1) = 0;
+
+ ret_obj = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:l,s:l,s:l,s:i,s:s}",
+ "nr_nodes", info.nr_nodes,
+ "max_cpu_id", info.max_cpu_id,
+ "threads_per_core", info.threads_per_core,
+ "cores_per_socket", info.cores_per_socket,
+ "sockets_per_node", info.sockets_per_node,
+ "total_memory", pages_to_kib(info.total_pages),
+ "free_memory", pages_to_kib(info.free_pages),
+ "scrub_memory", pages_to_kib(info.scrub_pages),
+ "cpu_khz", info.cpu_khz,
+ "hw_caps", cpu_cap);
+
+ max_cpu_id = info.max_cpu_id;
+ if ( max_cpu_id > MAX_CPU_ID )
+ max_cpu_id = MAX_CPU_ID;
+
+ /* Construct node-to-cpu lists. */
+ node_to_cpu_obj = PyList_New(0);
+
+ /* Make a list for each node. */
+ for ( i = 0; i < info.nr_nodes; i++ )
+ {
+ PyObject *cpus = PyList_New(0);
+ for ( j = 0; j <= max_cpu_id; j++ )
+ if ( i == map[j])
+ PyList_Append(cpus, PyInt_FromLong(j));
+ PyList_Append(node_to_cpu_obj, cpus);
+ }
+
+ PyDict_SetItemString(ret_obj, "node_to_cpu", node_to_cpu_obj);
+
+ return ret_obj;
+#undef MAX_CPU_ID
}
static PyObject *pyxc_xeninfo(XcObject *self)
diff --git a/tools/python/xen/util/acmpolicy.py b/tools/python/xen/util/acmpolicy.py
new file mode 100644
index 0000000000..f5fc292082
--- /dev/null
+++ b/tools/python/xen/util/acmpolicy.py
@@ -0,0 +1,1199 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#============================================================================
+# Copyright (C) 2006,2007 International Business Machines Corp.
+# Author: Stefan Berger <stefanb@us.ibm.com>
+#============================================================================
+
+import os
+import commands
+import struct
+import stat
+import array
+from xml.dom import minidom, Node
+from xen.xend.XendLogging import log
+from xen.util import security, xsconstants, bootloader, mkdir
+from xen.util.xspolicy import XSPolicy
+from xen.util.security import ACMError
+from xen.xend.XendError import SecurityError
+
+ACM_POLICIES_DIR = security.policy_dir_prefix + "/"
+
+# Constants needed for generating a binary policy from its XML
+# representation
+ACM_POLICY_VERSION = 3 # Latest one
+ACM_CHWALL_VERSION = 1
+
+ACM_STE_VERSION = 1
+
+ACM_MAGIC = 0x001debc;
+
+ACM_NULL_POLICY = 0
+ACM_CHINESE_WALL_POLICY = 1
+ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY = 2
+ACM_POLICY_UNDEFINED = 15
+
+
+ACM_SCHEMA_FILE = "/etc/xen/acm-security/policies/security_policy.xsd"
+
+class ACMPolicy(XSPolicy):
+ """
+ ACMPolicy class. Implements methods for getting information from
+ the XML representation of the policy as well as compilation and
+ loading of a policy into the HV.
+ """
+
+ def __init__(self, name=None, dom=None, ref=None, xml=None):
+ if name:
+ self.name = name
+ self.dom = minidom.parse(self.path_from_policy_name(name))
+ elif dom:
+ self.dom = dom
+ self.name = self.get_name()
+ elif xml:
+ self.dom = minidom.parseString(xml)
+ self.name = self.get_name()
+ rc = self.validate()
+ if rc != xsconstants.XSERR_SUCCESS:
+ raise SecurityError(rc)
+ mkdir.parents(ACM_POLICIES_DIR, stat.S_IRWXU)
+ if ref:
+ from xen.xend.XendXSPolicy import XendACMPolicy
+ self.xendacmpolicy = XendACMPolicy(self, {}, ref)
+ else:
+ self.xendacmpolicy = None
+ XSPolicy.__init__(self, name=self.name, ref=ref)
+
+ def get_dom(self):
+ return self.dom
+
+ def get_name(self):
+ return self.policy_dom_get_hdr_item("PolicyName")
+
+ def get_type(self):
+ return xsconstants.XS_POLICY_ACM
+
+ def get_type_name(self):
+ return xsconstants.ACM_POLICY_ID
+
+ def __str__(self):
+ return self.get_name()
+
+
+ def validate(self):
+ """
+ validate against the policy's schema Does not fail if the
+ libxml2 python lib is not installed
+ """
+ rc = xsconstants.XSERR_SUCCESS
+ try:
+ import libxml2
+ except Exception, e:
+ log.warn("Libxml2 python-wrapper is not installed on the system.")
+ return xsconstants.XSERR_SUCCESS
+ try:
+ parserctxt = libxml2.schemaNewParserCtxt(ACM_SCHEMA_FILE)
+ schemaparser = parserctxt.schemaParse()
+ valid = schemaparser.schemaNewValidCtxt()
+ doc = libxml2.parseDoc(self.toxml())
+ if doc.schemaValidateDoc(valid) != 0:
+ rc = -xsconstants.XSERR_BAD_XML
+ except Exception, e:
+ log.warn("Problem with the schema: %s" % str(e))
+ rc = -xsconstants.XSERR_GENERAL_FAILURE
+ if rc != xsconstants.XSERR_SUCCESS:
+ log.warn("XML did not validate against schema")
+ rc = self.__validate_name_and_labels()
+ return rc
+
+ def __validate_name_and_labels(self):
+ """ no ':' allowed in the policy name and the labels """
+ if ':' in self.get_name():
+ return -xsconstants.XSERR_BAD_POLICY_NAME
+ for s in self.policy_get_resourcelabel_names():
+ if ':' in s:
+ return -xsconstants.XSERR_BAD_LABEL
+ for s in self.policy_get_virtualmachinelabel_names():
+ if ':' in s:
+ return -xsconstants.XSERR_BAD_LABEL
+ return xsconstants.XSERR_SUCCESS
+
+
+ def update(self, xml_new):
+ """
+ Update the policy with the new XML. The hypervisor decides
+ whether the new policy can be applied.
+ """
+ rc = -xsconstants.XSERR_XML_PROCESSING
+ errors = ""
+ acmpol_old = self
+ try:
+ acmpol_new = ACMPolicy(xml=xml_new)
+ except Exception:
+ return -xsconstants.XSERR_XML_PROCESSING, errors
+
+ vmlabel_map = acmpol_new.policy_get_vmlabel_translation_map()
+ # An update requires version information in the current
+ # and new policy. The version number of the current policy
+ # must be the same as what is in the FromPolicy/Version node
+ # in the new one and the current policy's name must be the
+ # same as in FromPolicy/PolicyName
+
+ now_vers = acmpol_old.policy_dom_get_hdr_item("Version")
+ now_name = acmpol_old.policy_dom_get_hdr_item("PolicyName")
+ req_oldvers = acmpol_new.policy_dom_get_frompol_item("Version")
+ req_oldname = acmpol_new.policy_dom_get_frompol_item("PolicyName")
+
+ if now_vers == "" or \
+ now_vers != req_oldvers or \
+ now_name != req_oldname:
+ log.info("Policy rejected: %s != %s or %s != %s" % \
+ (now_vers,req_oldvers,now_name,req_oldname))
+ return -xsconstants.XSERR_VERSION_PREVENTS_UPDATE, errors
+
+ if not self.isVersionUpdate(acmpol_new):
+ log.info("Policy rejected since new version is not an update.")
+ return -xsconstants.XSERR_VERSION_PREVENTS_UPDATE, errors
+
+ if self.isloaded():
+ newvmnames = \
+ acmpol_new.policy_get_virtualmachinelabel_names_sorted()
+ oldvmnames = \
+ acmpol_old.policy_get_virtualmachinelabel_names_sorted()
+ del_array = ""
+ chg_array = ""
+ for o in oldvmnames:
+ if o not in newvmnames:
+ old_idx = oldvmnames.index(o) + 1 # for _NULL_LABEL_
+ if vmlabel_map.has_key(o):
+ #not a deletion, but a renaming
+ new = vmlabel_map[o]
+ new_idx = newvmnames.index(new) + 1 # for _NULL_LABEL_
+ chg_array += struct.pack("ii", old_idx, new_idx)
+ else:
+ del_array += struct.pack("i", old_idx)
+ for v in newvmnames:
+ if v in oldvmnames:
+ old_idx = oldvmnames.index(v) + 1 # for _NULL_LABEL_
+ new_idx = newvmnames.index(v) + 1 # for _NULL_LABEL_
+ if old_idx != new_idx:
+ chg_array += struct.pack("ii", old_idx, new_idx)
+
+ # VM labels indicated in the 'from' attribute of a VM or
+ # resource node but that did not exist in the old policy
+ # are considered bad labels.
+ bad_renamings = set(vmlabel_map.keys()) - set(oldvmnames)
+ if len(bad_renamings) > 0:
+ log.error("Bad VM label renamings: %s" %
+ list(bad_renamings))
+ return -xsconstants.XSERR_BAD_LABEL, errors
+
+ reslabel_map = acmpol_new.policy_get_reslabel_translation_map()
+ oldresnames = acmpol_old.policy_get_resourcelabel_names()
+ bad_renamings = set(reslabel_map.keys()) - set(oldresnames)
+ if len(bad_renamings) > 0:
+ log.error("Bad resource label renamings: %s" %
+ list(bad_renamings))
+ return -xsconstants.XSERR_BAD_LABEL, errors
+
+ #Get binary and map from the new policy
+ rc, map, bin_pol = acmpol_new.policy_create_map_and_bin()
+ if rc != xsconstants.XSERR_SUCCESS:
+ log.error("Could not build the map and binary policy.")
+ return rc, errors
+
+ #Need to do / check the following:
+ # - relabel all resources where there is a 'from' field in
+ # the policy and mark those as unlabeled where the label
+ # does not appear in the new policy anymore
+ # - relabel all VMs where there is a 'from' field in the
+ # policy and mark those as unlabeled where the label
+ # does not appear in the new policy anymore; no running
+ # or paused VM may be unlabeled through this
+ # - check that under the new labeling conditions the VMs
+ # still have access to their resources as before. Unlabeled
+ # resources are inaccessible. If this check fails, the
+ # update failed.
+ # - Attempt changes in the hypervisor; if this step fails,
+ # roll back the relabeling of resources and VMs
+ # - Commit the relabeling of resources
+
+
+ rc, errors = security.change_acm_policy(bin_pol,
+ del_array, chg_array,
+ vmlabel_map, reslabel_map,
+ self, acmpol_new)
+
+ if rc == 0:
+ # Replace the old DOM with the new one and save it
+ self.dom = acmpol_new.dom
+ self.compile()
+ log.info("ACM policy update was successful")
+ else:
+ #Not loaded in HV
+ self.dom = acmpol_new.dom
+ self.compile()
+ return rc, errors
+
+ def compareVersions(self, v1, v2):
+ """
+ Compare two policy versions given their tuples of major and
+ minor.
+ Return '0' if versions are equal, '>0' if v1 > v2 and
+ '<' if v1 < v2
+ """
+ rc = v1[0] - v2[0]
+ if rc == 0:
+ rc = v1[1] - v2[1]
+ return rc
+
+ def getVersionTuple(self, item="Version"):
+ v_str = self.policy_dom_get_hdr_item(item)
+ return self.__convVersionToTuple(v_str)
+
+ def get_version(self):
+ return self.policy_dom_get_hdr_item("Version")
+
+ def isVersionUpdate(self, polnew):
+ if self.compareVersions(polnew.getVersionTuple(),
+ self.getVersionTuple()) > 0:
+ return True
+ return False
+
+ def __convVersionToTuple(self, v_str):
+ """ Convert a version string, formatted according to the scheme
+ "%d.%d" into a tuple of (major, minor). Return (0,0) if the
+ string is empty.
+ """
+ major = 0
+ minor = 0
+ if v_str != "":
+ tmp = v_str.split(".")
+ major = int(tmp[0])
+ if len(tmp) > 1:
+ minor = int(tmp[1])
+ return (major, minor)
+
+
+ def policy_path(self, name, prefix = ACM_POLICIES_DIR ):
+ path = prefix + name.replace('.','/')
+ _path = path.split("/")
+ del _path[-1]
+ mkdir.parents("/".join(_path), stat.S_IRWXU)
+ return path
+
+ def path_from_policy_name(self, name):
+ return self.policy_path(name) + "-security_policy.xml"
+
+ #
+ # Functions interacting with the bootloader
+ #
+ def vmlabel_to_ssidref(self, vm_label):
+ """ Convert a VMlabel into an ssidref given the current
+ policy
+ Return xsconstants.INVALID_SSIDREF if conversion failed.
+ """
+ ssidref = xsconstants.INVALID_SSIDREF
+ names = self.policy_get_virtualmachinelabel_names_sorted()
+ try:
+ vmidx = names.index(vm_label) + 1 # for _NULL_LABEL_
+ ssidref = (vmidx << 16) | vmidx
+ except:
+ pass
+ return ssidref
+
+ def set_vm_bootlabel(self, vm_label):
+ parms="<>"
+ if vm_label != "":
+ ssidref = self.vmlabel_to_ssidref(vm_label)
+ if ssidref == xsconstants.INVALID_SSIDREF:
+ return -xsconstants.XSERR_BAD_LABEL
+ parms = "0x%08x:%s:%s:%s" % \
+ (ssidref, xsconstants.ACM_POLICY_ID, \
+ self.get_name(),vm_label)
+ else:
+ ssidref = 0 #Identifier for removal
+ try:
+ def_title = bootloader.get_default_title()
+ bootloader.set_kernel_attval(def_title, "ssidref", parms)
+ except:
+ return -xsconstants.XSERR_GENERAL_FAILURE
+ return ssidref
+
+ #
+ # Utility functions related to the policy's files
+ #
+ def get_filename(self, postfix, prefix = ACM_POLICIES_DIR, dotted=False):
+ """
+ Create the filename for the policy. The prefix is prepended
+ to the path. If dotted is True, then a policy name like
+ 'a.b.c' will remain as is, otherwise it will become 'a/b/c'
+ """
+ name = self.get_name()
+ if name:
+ p = name.split(".")
+ path = ""
+ if dotted == True:
+ sep = "."
+ else:
+ sep = "/"
+ if len(p) > 1:
+ path = sep.join(p[0:len(p)-1])
+ if prefix != "" or path != "":
+ allpath = prefix + path + sep + p[-1] + postfix
+ else:
+ allpath = p[-1] + postfix
+ return allpath
+ return None
+
+ def __readfile(self, name):
+ cont = ""
+ filename = self.get_filename(name)
+ f = open(filename, "r")
+ if f:
+ cont = f.read()
+ f.close()
+ return cont
+
+ def get_map(self):
+ return self.__readfile(".map")
+
+ def get_bin(self):
+ return self.__readfile(".bin")
+
+ #
+ # DOM-related functions
+ #
+
+ def policy_dom_get(self, parent, key, createit=False):
+ for node in parent.childNodes:
+ if node.nodeType == Node.ELEMENT_NODE:
+ if node.nodeName == key:
+ return node
+ if createit:
+ self.dom_create_node(parent, key)
+ return self.policy_dom_get(parent, key)
+
+ def dom_create_node(self, parent, newname, value=" "):
+ xml = "<a><"+newname+">"+ value +"</"+newname+"></a>"
+ frag = minidom.parseString(xml)
+ frag.childNodes[0].nodeType = Node.DOCUMENT_FRAGMENT_NODE
+ parent.appendChild(frag.childNodes[0])
+ return frag.childNodes[0]
+
+ def dom_get_node(self, path, createit=False):
+ node = None
+ parts = path.split("/")
+ doc = self.get_dom()
+ if len(parts) > 0:
+ node = self.policy_dom_get(doc.documentElement, parts[0])
+ if node:
+ i = 1
+ while i < len(parts):
+ _node = self.policy_dom_get(node, parts[i], createit)
+ if not _node:
+ if not createit:
+ break
+ else:
+ self.dom_create_node(node, parts[i])
+ _node = self.policy_dom_get(node, parts[i])
+ node = _node
+ i += 1
+ return node
+
+ #
+ # Header-related functions
+ #
+ def policy_dom_get_header_subnode(self, nodename):
+ node = self.dom_get_node("PolicyHeader/%s" % nodename)
+ return node
+
+ def policy_dom_get_hdr_item(self, name, default=""):
+ node = self.policy_dom_get_header_subnode(name)
+ if node and len(node.childNodes) > 0:
+ return node.childNodes[0].nodeValue
+ return default
+
+ def policy_dom_get_frompol_item(self, name, default="", createit=False):
+ node = self.dom_get_node("PolicyHeader/FromPolicy",createit)
+ if node:
+ node = self.policy_dom_get(node, name, createit)
+ if node and len(node.childNodes) > 0:
+ return node.childNodes[0].nodeValue
+ return default
+
+ def get_header_fields_map(self):
+ header = {
+ 'policyname' : self.policy_dom_get_hdr_item("PolicyName"),
+ 'policyurl' : self.policy_dom_get_hdr_item("PolicyUrl"),
+ 'reference' : self.policy_dom_get_hdr_item("Reference"),
+ 'date' : self.policy_dom_get_hdr_item("Date"),
+ 'namespaceurl' : self.policy_dom_get_hdr_item("NameSpaceUrl"),
+ 'version' : self.policy_dom_get_hdr_item("Version")
+ }
+ return header
+
+ def set_frompolicy_name(self, name):
+ """ For tools to adapt the header of the policy """
+ node = self.dom_get_node("PolicyHeader/FromPolicy/PolicyName",
+ createit=True)
+ node.childNodes[0].nodeValue = name
+
+ def set_frompolicy_version(self, version):
+ """ For tools to adapt the header of the policy """
+ node = self.dom_get_node("PolicyHeader/FromPolicy/Version",
+ createit=True)
+ node.childNodes[0].nodeValue = version
+
+ def set_policy_name(self, name):
+ """ For tools to adapt the header of the policy """
+ node = self.dom_get_node("PolicyHeader/PolicyName")
+ node.childNodes[0].nodeValue = name
+
+ def set_policy_version(self, version):
+ """ For tools to adapt the header of the policy """
+ node = self.dom_get_node("PolicyHeader/Version")
+ node.childNodes[0].nodeValue = version
+
+ def update_frompolicy(self, curpol):
+ self.set_frompolicy_name(curpol.policy_dom_get_hdr_item("PolicyName"))
+ version = curpol.policy_dom_get_hdr_item("Version")
+ self.set_frompolicy_version(version)
+ (maj, min) = self.__convVersionToTuple(version)
+ self.set_policy_version("%s.%s" % (maj, min+1))
+
+ #
+ # Get all types that are part of a node
+ #
+
+ def policy_get_types(self, node):
+ strings = []
+ i = 0
+ while i < len(node.childNodes):
+ if node.childNodes[i].nodeName == "Type":
+ strings.append(node.childNodes[i].childNodes[0].nodeValue)
+ i += 1
+ return strings
+
+ #
+ # Simple Type Enforcement-related functions
+ #
+
+ def policy_get_stetypes_node(self):
+ node = self.dom_get_node("SimpleTypeEnforcement/SimpleTypeEnforcementTypes")
+ return node
+
+ def policy_get_stetypes_types(self):
+ strings = []
+ node = self.policy_get_stetypes_node()
+ if node:
+ strings = self.policy_get_types(node)
+ return strings
+
+ #
+ # Chinese Wall Type-related functions
+ #
+
+ def policy_get_chwall_types(self):
+ strings = []
+ node = self.dom_get_node("ChineseWall/ChineseWallTypes")
+ if node:
+ strings = self.policy_get_types(node)
+ return strings
+
+ def policy_get_chwall_cfses(self):
+ cfs = []
+ node = self.dom_get_node("ChineseWall/ConflictSets")
+ if node:
+ i = 0
+ while i < len(node.childNodes):
+ _cfs = {}
+ if node.childNodes[i].nodeName == "Conflict":
+ _cfs['name'] = node.childNodes[i].getAttribute('name')
+ _cfs['chws'] = self.policy_get_types(node.childNodes[i])
+ cfs.append(_cfs)
+ i += 1
+ return cfs
+
+ def policy_get_chwall_cfses_names_sorted(self):
+ """
+ Return the list of all conflict set names in alphabetical
+ order.
+ """
+ cfs_names = []
+ node = self.dom_get_node("ChineseWall/ConflictSets")
+ if node:
+ i = 0
+ while i < len(node.childNodes):
+ if node.childNodes[i].nodeName == "Conflict":
+ n = node.childNodes[i].getAttribute('name')
+ #it better have a name!
+ if n:
+ cfs_names.append(n)
+ i += 1
+ cfs_names.sort()
+ return cfs_names
+
+ #
+ # Subject Label-related functions
+ #
+
+ def policy_get_bootstrap_vmlabel(self):
+ node = self.dom_get_node("SecurityLabelTemplate/SubjectLabels")
+ if node:
+ vmlabel = node.getAttribute("bootstrap")
+ return vmlabel
+
+ # Get the names of all virtual machine labels; returns an array
+ def policy_get_virtualmachinelabel_names(self):
+ strings = []
+ node = self.dom_get_node("SecurityLabelTemplate/SubjectLabels")
+ if node:
+ i = 0
+ while i < len(node.childNodes):
+ if node.childNodes[i].nodeName == "VirtualMachineLabel":
+ name = self.policy_dom_get(node.childNodes[i], "Name")
+ strings.append(name.childNodes[0].nodeValue)
+ i += 1
+ return strings
+
+ def policy_sort_virtualmachinelabel_names(self, vmnames):
+ bootstrap = self.policy_get_bootstrap_vmlabel()
+ if bootstrap not in vmnames:
+ raise SecurityError(-xsconstants.XSERR_POLICY_INCONSISTENT)
+ vmnames.remove(bootstrap)
+ vmnames.sort()
+ vmnames.insert(0, bootstrap)
+ return vmnames
+
+ def policy_get_virtualmachinelabel_names_sorted(self):
+ """ Get a sorted list of VMlabel names. The bootstrap VM's
+ label will be the first one in that list, followed
+ by an alphabetically sorted list of VM label names """
+ vmnames = self.policy_get_virtualmachinelabel_names()
+ return self.policy_sort_virtualmachinelabel_names(vmnames)
+
+ def policy_get_virtualmachinelabels(self):
+ """ Get a list of all virtual machine labels in this policy """
+ res = []
+ node = self.dom_get_node("SecurityLabelTemplate/SubjectLabels")
+ if node:
+ i = 0
+ while i < len(node.childNodes):
+ if node.childNodes[i].nodeName == "VirtualMachineLabel":
+ _res = {}
+ _res['type'] = xsconstants.ACM_LABEL_VM
+ name = self.policy_dom_get(node.childNodes[i], "Name")
+ _res['name'] = name.childNodes[0].nodeValue
+ stes = self.policy_dom_get(node.childNodes[i],
+ "SimpleTypeEnforcementTypes")
+ if stes:
+ _res['stes'] = self.policy_get_types(stes)
+ else:
+ _res['stes'] = []
+ chws = self.policy_dom_get(node.childNodes[i],
+ "ChineseWallTypes")
+ if chws:
+ _res['chws'] = self.policy_get_types(chws)
+ else:
+ _res['chws'] = []
+ res.append(_res)
+ i += 1
+ return res
+
+ def policy_get_stes_of_vmlabel(self, vmlabel):
+ """ Get a list of all STEs of a given VMlabel """
+ return self.__policy_get_stes_of_labeltype(vmlabel,
+ "VirtualMachineLabel")
+
+ def policy_get_stes_of_resource(self, reslabel):
+ """ Get a list of all resources of a given VMlabel """
+ return self.__policy_get_stes_of_labeltype(reslabel, "ResourceLabel")
+
+ def __policy_get_stes_of_labeltype(self, label, labeltype):
+ node = self.dom_get_node("SecurityLabelTemplate/SubjectLabels")
+ if node:
+ i = 0
+ while i < len(node.childNodes):
+ if node.childNodes[i].nodeName == labeltype:
+ name = self.policy_dom_get(node.childNodes[i], "Name")
+ if name.childNodes[0].nodeValue == label:
+ stes = self.policy_dom_get(node.childNodes[i],
+ "SimpleTypeEnforcementTypes")
+ if not stes:
+ return []
+ return self.policy_get_types(stes)
+ i += 1
+ return []
+
+ def policy_check_vmlabel_against_reslabels(self, vmlabel, resources):
+ """
+ Check whether the given vmlabel is compatible with the given
+ resource labels. Do this by getting all the STEs of the
+ vmlabel and the STEs of the resources. Any STE type of the
+ VM label must match an STE type of the resource.
+ """
+ vm_stes = self.policy_get_stes_of_vmlabel(vmlabel)
+ if len(vm_stes) == 0:
+ return False
+ for res in resources:
+ res_stes = self.policy_get_stes_of_resource(res)
+ if len( set(res_stes).union( set(vm_stes) ) ) == 0:
+ return False
+ return True
+
+ def __policy_get_label_translation_map(self, path, labeltype):
+ res = {}
+ node = self.dom_get_node("SecurityLabelTemplate/" + path)
+ if node:
+ i = 0
+ while i < len(node.childNodes):
+ if node.childNodes[i].nodeName == labeltype:
+ name = self.policy_dom_get(node.childNodes[i], "Name")
+ from_name = name.getAttribute("from")
+ if from_name:
+ res.update({from_name : name.childNodes[0].nodeValue})
+ i += 1
+ return res
+
+ def policy_get_vmlabel_translation_map(self):
+ """
+ Get a dictionary of virtual machine mappings from their
+ old VMlabel name to the new VMlabel name.
+ """
+ return self.__policy_get_label_translation_map("SubjectLabels",
+ "VirtualMachineLabel")
+
+ def policy_get_reslabel_translation_map(self):
+ """
+ Get a dictionary of resource mappings from their
+ old resource label name to the new resource label name.
+ """
+ return self.__policy_get_label_translation_map("ObjectLabels",
+ "ResourceLabel")
+
+ #
+ # Object Label-related functions
+ #
+ def policy_get_resourcelabel_names(self):
+ """
+ Get the names of all resource labels in an array but
+ only those that actually have types
+ """
+ strings = []
+ node = self.dom_get_node("SecurityLabelTemplate/ObjectLabels")
+ if node:
+ i = 0
+ while i < len(node.childNodes):
+ if node.childNodes[i].nodeName == "ResourceLabel":
+ name = self.policy_dom_get(node.childNodes[i], "Name")
+ stes = self.policy_dom_get(node.childNodes[i],
+ "SimpleTypeEnforcementTypes")
+ if stes:
+ strings.append(name.childNodes[0].nodeValue)
+ i += 1
+ return strings
+
+ def policy_get_resourcelabels(self):
+ """
+ Get all information about all resource labels of this policy.
+ """
+ res = []
+ node = self.dom_get_node("SecurityLabelTemplate/ObjectLabels")
+ if node:
+ i = 0
+ while i < len(node.childNodes):
+ if node.childNodes[i].nodeName == "ResourceLabel":
+ _res = {}
+ _res['type'] = xsconstants.ACM_LABEL_RES
+ name = self.policy_dom_get(node.childNodes[i], "Name")
+ _res['name'] = name.childNodes[0].nodeValue
+ stes = self.policy_dom_get(node.childNodes[i],
+ "SimpleTypeEnforcementTypes")
+ if stes:
+ _res['stes'] = self.policy_get_types(stes)
+ else:
+ _res['stes'] = []
+ _res['chws'] = []
+ res.append(_res)
+ i += 1
+ return res
+
+
+ def policy_find_reslabels_with_stetype(self, stetype):
+ """
+ Find those resource labels that hold a given STE type.
+ """
+ res = []
+ reslabels = self.policy_get_resourcelabels()
+ for resl in reslabels:
+ if stetype in resl['stes']:
+ res.append(resl['name'])
+ return res
+
+
+ def toxml(self):
+ dom = self.get_dom()
+ if dom:
+ return dom.toxml()
+ return None
+
+ def save(self):
+ ### Save the XML policy into a file ###
+ rc = -xsconstants.XSERR_FILE_ERROR
+ name = self.get_name()
+ if name:
+ path = self.path_from_policy_name(name)
+ if path:
+ f = open(path, 'w')
+ if f:
+ f.write(self.toxml())
+ f.close()
+ rc = 0
+ return rc
+
+ def __write_to_file(self, suffix, data):
+ #write the data into a file with the given suffix
+ f = open(self.get_filename(suffix),"w")
+ if f:
+ try:
+ try:
+ f.write(data)
+ except Exception, e:
+ log.error("Error writing file: %s" % str(e))
+ return -xsconstants.XSERR_FILE_ERROR
+ finally:
+ f.close()
+ else:
+ return -xsconstants.XSERR_FILE_ERROR
+ return xsconstants.XSERR_SUCCESS
+
+
+ def compile(self):
+ rc = self.save()
+ if rc == 0:
+ rc, mapfile, bin_pol = self.policy_create_map_and_bin()
+
+ if rc == 0:
+ rc = self.__write_to_file(".map", mapfile)
+ if rc != 0:
+ log.error("Error writing map file")
+
+ if rc == 0:
+ rc = self.__write_to_file(".bin", bin_pol)
+ if rc != 0:
+ log.error("Error writing binary policy file")
+ return rc
+
+ def loadintohv(self):
+ """
+ load this policy into the hypervisor
+ if successful,the policy's flags will indicate that the
+ policy is the one loaded into the hypervisor
+ """
+ (ret, output) = commands.getstatusoutput(
+ security.xensec_tool +
+ " loadpolicy " +
+ self.get_filename(".bin"))
+ if ret != 0:
+ return -xsconstants.XSERR_POLICY_LOAD_FAILED
+ return xsconstants.XSERR_SUCCESS
+
+ def isloaded(self):
+ """
+ Determine whether this policy is the active one.
+ """
+ security.refresh_security_policy()
+ if self.get_name() == security.active_policy:
+ return True
+ return False
+
+ def destroy(self):
+ """
+ Destroy the policy including its binary, mapping and
+ XML files.
+ This only works if the policy is not the one that's loaded
+ """
+ if self.isloaded():
+ return -xsconstants.XSERR_POLICY_LOADED
+ files = [ self.get_filename(".map",""),
+ self.get_filename(".bin",""),
+ self.path_from_policy_name(self.get_name())]
+ for f in files:
+ try:
+ os.unlink(f)
+ except:
+ pass
+ if self.xendacmpolicy:
+ self.xendacmpolicy.destroy()
+ XSPolicy.destroy(self)
+ return xsconstants.XSERR_SUCCESS
+
+ def policy_get_domain_label(self, domid):
+ """
+ Given a domain's ID, retrieve the label it has using
+ its ssidref for reverse calculation.
+ """
+ try:
+ mgmt_dom = security.get_ssid(domid)
+ except:
+ return ""
+ return self.policy_get_domain_label_by_ssidref(int(mgmt_dom[3]))
+
+ def policy_get_domain_label_by_ssidref(self, ssidref):
+ """ Given an ssidref, find the corresponding VM label """
+ chwall_ref = ssidref & 0xffff
+ try:
+ allvmtypes = self.policy_get_virtualmachinelabel_names_sorted()
+ except:
+ return None
+ return allvmtypes[chwall_ref-1] # skip _NULL_LABEL_
+
+ def policy_get_domain_label_formatted(self, domid):
+ label = self.policy_get_domain_label(domid)
+ if label == "":
+ return ""
+ return "%s:%s:%s" % (xsconstants.ACM_POLICY_ID, self.get_name(), label)
+
+ def policy_get_domain_label_by_ssidref_formatted(self, ssidref):
+ label = self.policy_get_domain_label_by_ssidref(ssidref)
+ if label == "":
+ return ""
+ return "%s:%s:%s" % (xsconstants.ACM_POLICY_ID, self.get_name(), label)
+
+ def policy_create_map_and_bin(self):
+ """
+ Create the policy's map and binary files -- compile the policy.
+ """
+ def roundup8(len):
+ return ((len + 7) & ~7)
+
+ rc = xsconstants.XSERR_SUCCESS
+ mapfile = ""
+ primpolcode = ACM_POLICY_UNDEFINED
+ secpolcode = ACM_POLICY_UNDEFINED
+ unknown_ste = set()
+ unknown_chw = set()
+
+ rc = self.validate()
+ if rc:
+ return rc, "", ""
+
+ stes = self.policy_get_stetypes_types()
+ if stes:
+ stes.sort()
+
+ chws = self.policy_get_chwall_types()
+ if chws:
+ chws.sort()
+
+ vms = self.policy_get_virtualmachinelabels()
+ bootstrap = self.policy_get_bootstrap_vmlabel()
+
+ vmlabels = self.policy_get_virtualmachinelabel_names_sorted()
+ if bootstrap not in vmlabels:
+ log.error("Bootstrap label '%s' not found among VM labels '%s'." \
+ % (bootstrap, vmlabels))
+ return -xsconstants.XSERR_POLICY_INCONSISTENT, "", ""
+
+ vms_with_chws = []
+ chws_by_vm = {}
+ for v in vms:
+ if v.has_key("chws"):
+ vms_with_chws.append(v["name"])
+ chws_by_vm[v["name"]] = v["chws"]
+ if bootstrap in vms_with_chws:
+ vms_with_chws.remove(bootstrap)
+ vms_with_chws.sort()
+ vms_with_chws.insert(0, bootstrap)
+ else:
+ vms_with_chws.sort()
+
+ vms_with_stes = []
+ stes_by_vm = {}
+ for v in vms:
+ if v.has_key("stes"):
+ vms_with_stes.append(v["name"])
+ stes_by_vm[v["name"]] = v["stes"]
+ if bootstrap in vms_with_stes:
+ vms_with_stes.remove(bootstrap)
+ vms_with_stes.sort()
+ vms_with_stes.insert(0, bootstrap)
+ else:
+ vms_with_stes.sort()
+
+ resnames = self.policy_get_resourcelabel_names()
+ resnames.sort()
+ stes_by_res = {}
+ res = self.policy_get_resourcelabels()
+ for r in res:
+ if r.has_key("stes"):
+ stes_by_res[r["name"]] = r["stes"]
+
+ max_chw_ssids = 1 + len(vms_with_chws)
+ max_chw_types = 1 + len(vms_with_chws)
+ max_ste_ssids = 1 + len(vms_with_stes) + len(resnames)
+ max_ste_types = 1 + len(vms_with_stes) + len(resnames)
+
+ mapfile = "POLICYREFERENCENAME %s\n" % self.get_name()
+ mapfile += "MAGIC %08x\n" % ACM_MAGIC
+ mapfile += "POLICFILE %s\n" % \
+ self.path_from_policy_name(self.get_name())
+ mapfile += "BINARYFILE %s\n" % self.get_filename(".bin")
+ mapfile += "MAX-CHWALL-TYPES %08x\n" % len(chws)
+ mapfile += "MAX-CHWALL-SSIDS %08x\n" % max_chw_ssids
+ mapfile += "MAX-CHWALL-LABELS %08x\n" % max_chw_ssids
+ mapfile += "MAX-STE-TYPES %08x\n" % len(stes)
+ mapfile += "MAX-STE-SSIDS %08x\n" % max_ste_ssids
+ mapfile += "MAX-STE-LABELS %08x\n" % max_ste_ssids
+ mapfile += "\n"
+
+ if chws:
+ mapfile += \
+ "PRIMARY CHWALL\n"
+ primpolcode = ACM_CHINESE_WALL_POLICY
+ if stes:
+ mapfile += \
+ "SECONDARY STE\n"
+ else:
+ mapfile += \
+ "SECONDARY NULL\n"
+ secpolcode = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY
+ else:
+ if stes:
+ mapfile += \
+ "PRIMARY STE\n"
+ primpolcode = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY
+ mapfile += \
+ "SECONDARY NULL\n"
+
+ mapfile += "\n"
+
+ if len(vms_with_chws) > 0:
+ mapfile += \
+ "LABEL->SSID ANY CHWALL __NULL_LABEL__ %x\n" % 0
+ i = 0
+ for v in vms_with_chws:
+ mapfile += \
+ "LABEL->SSID VM CHWALL %-20s %x\n" % \
+ (v, i+1)
+ i += 1
+ mapfile += "\n"
+
+ if len(vms_with_stes) > 0 or len(resnames) > 0:
+ mapfile += \
+ "LABEL->SSID ANY STE __NULL_LABEL__ %08x\n" % 0
+ i = 0
+ for v in vms_with_stes:
+ mapfile += \
+ "LABEL->SSID VM STE %-20s %x\n" % (v, i+1)
+ i += 1
+ j = 0
+ for r in resnames:
+ mapfile += \
+ "LABEL->SSID RES STE %-20s %x\n" % (r, j+i+1)
+ j += 1
+ mapfile += "\n"
+
+ if vms_with_chws:
+ mapfile += \
+ "SSID->TYPE CHWALL %08x\n" % 0
+ i = 1
+ for v in vms_with_chws:
+ mapfile += \
+ "SSID->TYPE CHWALL %08x" % i
+ for c in chws_by_vm[v]:
+ mapfile += " %s" % c
+ mapfile += "\n"
+ i += 1
+ mapfile += "\n"
+
+ if len(vms_with_stes) > 0 or len(resnames) > 0:
+ mapfile += \
+ "SSID->TYPE STE %08x\n" % 0
+ i = 1
+ for v in vms_with_stes:
+ mapfile += \
+ "SSID->TYPE STE %08x" % i
+ for s in stes_by_vm[v]:
+ mapfile += " %s" % s
+ mapfile += "\n"
+ i += 1
+
+ for r in resnames:
+ mapfile += \
+ "SSID->TYPE STE %08x" % i
+ for s in stes_by_res[r]:
+ mapfile += " %s" % s
+ mapfile += "\n"
+ i += 1
+ mapfile += "\n"
+
+ if chws:
+ i = 0
+ while i < len(chws):
+ mapfile += \
+ "TYPE CHWALL %-20s %d\n" % (chws[i], i)
+ i += 1
+ mapfile += "\n"
+ if stes:
+ i = 0
+ while i < len(stes):
+ mapfile += \
+ "TYPE STE %-20s %d\n" % (stes[i], i)
+ i += 1
+ mapfile += "\n"
+
+ mapfile += "\n"
+
+ # Build header with policy name
+ length = roundup8(4 + len(self.get_name()) + 1)
+ polname = self.get_name();
+ pr_bin = struct.pack("!i", len(polname)+1)
+ pr_bin += polname;
+ while len(pr_bin) < length:
+ pr_bin += "\x00"
+
+ # Build chinese wall part
+ cfses_names = self.policy_get_chwall_cfses_names_sorted()
+ cfses = self.policy_get_chwall_cfses()
+
+ chwformat = "!iiiiiiiii"
+ max_chw_cfs = len(cfses)
+ chw_ssid_offset = struct.calcsize(chwformat)
+ chw_confset_offset = chw_ssid_offset + \
+ 2 * len(chws) * max_chw_types
+ chw_running_types_offset = 0
+ chw_conf_agg_offset = 0
+
+ chw_bin = struct.pack(chwformat,
+ ACM_CHWALL_VERSION,
+ ACM_CHINESE_WALL_POLICY,
+ len(chws),
+ max_chw_ssids,
+ max_chw_cfs,
+ chw_ssid_offset,
+ chw_confset_offset,
+ chw_running_types_offset,
+ chw_conf_agg_offset)
+ chw_bin_body = ""
+ # simulate __NULL_LABEL__
+ for c in chws:
+ chw_bin_body += struct.pack("!h",0)
+ # VMs that are listed and their chinese walls
+ for v in vms_with_chws:
+ for c in chws:
+ unknown_chw |= (set(chws_by_vm[v]) - set(chws))
+ if c in chws_by_vm[v]:
+ chw_bin_body += struct.pack("!h",1)
+ else:
+ chw_bin_body += struct.pack("!h",0)
+
+ # Conflict sets -- they need to be processed in alphabetical order
+ for cn in cfses_names:
+ if cn == "" or cn is None:
+ return -xsconstants.XSERR_BAD_CONFLICTSET, "", ""
+ i = 0
+ while i < len(cfses):
+ if cfses[i]['name'] == cn:
+ conf = cfses[i]['chws']
+ break
+ i += 1
+ for c in chws:
+ if c in conf:
+ chw_bin_body += struct.pack("!h",1)
+ else:
+ chw_bin_body += struct.pack("!h",0)
+ del cfses[i]
+
+ if len(cfses) != 0:
+ return -xsconstants.XSERR_BAD_CONFLICTSET, "", ""
+
+ chw_bin += chw_bin_body
+
+ while len(chw_bin) < roundup8(len(chw_bin)):
+ chw_bin += "\x00"
+
+ # Build STE part
+ steformat="!iiiii"
+ ste_bin = struct.pack(steformat,
+ ACM_STE_VERSION,
+ ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
+ len(stes),
+ max_ste_types,
+ struct.calcsize(steformat))
+ ste_bin_body = ""
+ if stes:
+ # Simulate __NULL_LABEL__
+ for s in stes:
+ ste_bin_body += struct.pack("!h",0)
+ # VMs that are listed and their chinese walls
+ for v in vms_with_stes:
+ unknown_ste |= (set(stes_by_vm[v]) - set(stes))
+ for s in stes:
+ if s in stes_by_vm[v]:
+ ste_bin_body += struct.pack("!h",1)
+ else:
+ ste_bin_body += struct.pack("!h",0)
+ for r in resnames:
+ unknown_ste |= (set(stes_by_res[r]) - set(stes))
+ for s in stes:
+ if s in stes_by_res[r]:
+ ste_bin_body += struct.pack("!h",1)
+ else:
+ ste_bin_body += struct.pack("!h",0)
+
+ ste_bin += ste_bin_body;
+
+ while len(ste_bin) < roundup8(len(ste_bin)):
+ ste_bin += "\x00"
+
+ #Write binary header:
+ headerformat="!iiiiiiiiii"
+ totallen_bin = struct.calcsize(headerformat) + \
+ len(pr_bin) + len(chw_bin) + len(ste_bin)
+ polref_offset = struct.calcsize(headerformat)
+ primpoloffset = polref_offset + len(pr_bin)
+ if primpolcode == ACM_CHINESE_WALL_POLICY:
+ secpoloffset = primpoloffset + len(chw_bin)
+ elif primpolcode == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
+ secpoloffset = primpoloffset + len(ste_bin)
+ else:
+ secpoloffset = primpoloffset
+
+ (major, minor) = self.getVersionTuple()
+ hdr_bin = struct.pack(headerformat,
+ ACM_POLICY_VERSION,
+ ACM_MAGIC,
+ totallen_bin,
+ polref_offset,
+ primpolcode,
+ primpoloffset,
+ secpolcode,
+ secpoloffset,
+ major, minor)
+
+ all_bin = array.array('B')
+ for s in [ hdr_bin, pr_bin, chw_bin, ste_bin ]:
+ for c in s:
+ all_bin.append(ord(c))
+
+ log.info("Compiled policy: rc = %s" % hex(rc))
+ if len(unknown_ste) > 0:
+ log.info("The following STEs in VM/res labels were unknown:" \
+ " %s" % list(unknown_ste))
+ if len(unknown_chw) > 0:
+ log.info("The following Ch. Wall types in labels were unknown:" \
+ " %s" % list(unknown_chw))
+ return rc, mapfile, all_bin.tostring()
diff --git a/tools/python/xen/util/bootloader.py b/tools/python/xen/util/bootloader.py
new file mode 100644
index 0000000000..8660bd8956
--- /dev/null
+++ b/tools/python/xen/util/bootloader.py
@@ -0,0 +1,521 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#============================================================================
+# Copyright (C) 2006,2007 International Business Machines Corp.
+# Author: Stefan Berger <stefanb@us.ibm.com>
+#============================================================================
+
+import re
+import os, stat
+import tempfile
+import shutil
+import threading
+from xen.xend.XendLogging import log
+
+__bootloader = None
+
+#
+# Functions for modifying entries in the bootloader, i.e. adding
+# a module to boot the system with a policy.
+#
+
+def get_default_title():
+ """ See description in Bootloader class below """
+ return __bootloader.get_default_title()
+
+
+def get_boot_policies():
+ """ See description in Bootloader class below """
+ return __bootloader.get_boot_policies()
+
+
+def add_boot_policy(index, binpolname):
+ """ See description in Bootloader class below """
+ return __bootloader.add_boot_policy(index, binpolname)
+
+
+def rm_policy_from_boottitle(index, unamelist):
+ """ See description in Bootloader class below """
+ return __bootloader.rm_policy_from_boottitle(index, unamelist)
+
+
+def set_kernel_attval(index, att, val):
+ """ See description in Bootloader class below """
+ return __bootloader.set_kernel_attval(index, att, val)
+
+
+def get_kernel_val(index, att):
+ """ See description in Bootloader class below """
+ return __bootloader.get_kernel_val(index, att)
+
+
+def set_boot_policy(title_idx, filename):
+ boottitles = get_boot_policies()
+ if boottitles.has_key(title_idx):
+ rm_policy_from_boottitle(title_idx, [ boottitles[title_idx] ])
+ rc = add_boot_policy(title_idx, filename)
+ return rc
+
+
+def loads_default_policy(filename):
+ """ Determine whether the given policy is loaded by the default boot title """
+ polfile = get_default_policy()
+ if polfile != None:
+ if polfile == filename or \
+ "/"+polfile == filename:
+ return True
+ return False
+
+
+def get_default_policy():
+ """ Get the name of the policy loaded by the default boot title """
+ title = get_default_title()
+ policies = get_boot_policies()
+ return policies.get(title)
+
+
+def set_default_boot_policy(filename):
+ """ Set the boot policy in the default title to the given name. """
+ title = get_default_title()
+ return set_boot_policy(title, filename)
+
+
+def __is_bootdir_mounted():
+ """
+ Determine whether the boot partition /boot is mounted or not
+ """
+ rc = False
+ file = open("/proc/mounts")
+ for line in file:
+ tmp = line.split(" ")
+ if tmp[1] == "/boot":
+ rc = True
+ break
+ return rc
+
+def get_prefix():
+ if __is_bootdir_mounted():
+ return "/"
+ else:
+ return "/boot/"
+
+
+
+class Bootloader:
+ """ Bootloader class that real bootloader implementations must overwrite """
+ def __init__(self):
+ pass
+
+ def probe(self):
+ """ Test whether this implementation of a bootloader is supported on the
+ local system """
+ return True
+
+ def get_default_title(self):
+ """ Get the index (starting with 0) of the default boot title
+ This number is read from the grub configuration file.
+ In case of an error '-1' is returned
+ @rtype: int
+ @return: the index of the default boot title
+ """
+ return None
+
+ def get_boot_policies(self):
+ """ Get a dictionary of policies that the system is booting with.
+ @rtype: dict
+ @return: dictionary of boot titles where the keys are the
+ indices of the boot titles
+ """
+ return {}
+
+ def add_boot_policy(self, index, binpolname):
+ """ Add the binary policy for automatic loading when
+ booting the system. Add it to the boot title at index
+ 'index'.
+ """
+ return False
+
+ def rm_policy_from_boottitle(self, index, unamelist):
+ """ Remove a policy from the given title. A list of possible policies
+ must be given to detect what module to remove
+ """
+ return False
+
+ def set_kernel_attval(self, index, att, val):
+ """
+ Append an attribut/value pair to the kernel line.
+ @param index : The index of the title to modify
+ @param att : The attribute to add
+ @param val : The value to add. If no value or the special value
+ '<>' is given, then the attribute will be removed.
+ If an empty value is given, then only the attribute
+ is added in the format "att", otherwise "att=val"
+ is added.
+ """
+ return False
+
+ def get_kernel_val(self, index, att):
+ """
+ Get an attribute's value from the kernel line.
+ @param index : The index of the title to get the attribute/value from
+ @param att : The attribute to read the value of
+ """
+ return None
+
+
+class Grub(Bootloader):
+ """ Implementation for manipulating bootloader entries in grub according
+ to the 'Bootloader' class interface """
+
+ def __init__(self):
+ self.__bootfile_lock = threading.RLock()
+ self.title_re = re.compile("\s*title\s", re.IGNORECASE)
+ self.module_re = re.compile("\s+module\s", re.IGNORECASE)
+ self.policy_re = re.compile(".*\.bin", re.IGNORECASE)
+ self.kernel_re = re.compile("\s*kernel\s", re.IGNORECASE)
+ Bootloader.__init__(self)
+
+ def probe(self):
+ try:
+ boot_file = self.__get_bootfile()
+ except:
+ return False
+ return True
+
+
+ def __get_bootfile(self):
+ """ Get the name of the bootfile """
+ boot_file = "/boot/grub/grub.conf"
+ alt_boot_file = "/boot/grub/menu.lst"
+
+ if not os.path.isfile(boot_file):
+ #take alternate boot file instead
+ boot_file = alt_boot_file
+
+ #follow symlink since menue.lst might be linked to grub.conf
+ if not os.path.exists(boot_file):
+ raise IOError("Boot file \'%s\' not found." % boot_file)
+
+ if stat.S_ISLNK(os.lstat(boot_file)[stat.ST_MODE]):
+ new_name = os.readlink(boot_file)
+ if new_name[0] == "/":
+ boot_file = new_name
+ else:
+ path = boot_file.split('/')
+ path[len(path)-1] = new_name
+ boot_file = '/'.join(path)
+ if not os.path.exists(boot_file):
+ raise IOError("Boot file \'%s\' not found." % boot_file)
+ return boot_file
+
+
+ def __get_titles(self):
+ """ Get the names of all boot titles in the grub config file
+ @rtype: list
+ @return: list of names of available boot titles
+ """
+ titles = []
+ try:
+ boot_file = self.__get_bootfile()
+ except:
+ return []
+ try:
+ self.__bootfile_lock.acquire()
+ grub_fd = open(boot_file)
+ for line in grub_fd:
+ if self.title_re.match(line):
+ line = line.rstrip().lstrip()
+ titles.append(line.lstrip('title').lstrip())
+ finally:
+ self.__bootfile_lock.release()
+ return titles
+
+
+ def get_default_title(self):
+ """ Get the index (starting with 0) of the default boot title
+ This number is read from the grub configuration file.
+ In case of an error '-1' is returned
+ @rtype: int
+ @return: the index of the default boot title
+ """
+ def_re = re.compile("default", re.IGNORECASE)
+ default = None
+ try:
+ boot_file = self.__get_bootfile()
+ except:
+ return default
+ try:
+ self.__bootfile_lock.acquire()
+ grub_fd = open(boot_file)
+ for line in grub_fd:
+ line = line.rstrip()
+ if def_re.match(line):
+ line = line.rstrip()
+ line = line.lstrip("default=")
+ default = int(line)
+ break
+ finally:
+ self.__bootfile_lock.release()
+ return default
+
+
+ def get_boot_policies(self):
+ """ Get a dictionary of policies that the system is booting with.
+ @rtype: dict
+ @return: dictionary of boot titles where the keys are the
+ indices of the boot titles
+ """
+ policies = {}
+ within_title = 0
+ idx = -1
+ try:
+ boot_file = self.__get_bootfile()
+ except:
+ return policies
+ try:
+ self.__bootfile_lock.acquire()
+
+ grub_fd = open(boot_file)
+ for line in grub_fd:
+ if self.title_re.match(line):
+ within_title = 1
+ idx = idx + 1
+ if within_title and self.module_re.match(line):
+ if self.policy_re.match(line):
+ start = line.find("module")
+ pol = line[start+6:]
+ pol = pol.lstrip().rstrip()
+ if pol[0] == '/':
+ pol = pol[1:]
+ if pol[0:5] == "boot/":
+ pol = pol[5:]
+ policies[idx] = pol
+ finally:
+ self.__bootfile_lock.release()
+ return policies
+
+
+ def add_boot_policy(self, index, binpolname):
+ """ Add the binary policy for automatic loading when
+ booting the system. Add it to the boot title at index
+ 'index'.
+ """
+ ctr = 0
+ module_line = ""
+ within_title = 0
+ found = False
+ try:
+ boot_file = self.__get_bootfile()
+ except:
+ return False
+ try:
+ self.__bootfile_lock.acquire()
+ grub_fd = open(boot_file)
+ (tmp_fd, tmp_grub) = tempfile.mkstemp()
+ for line in grub_fd:
+ if self.title_re.match(line):
+ if module_line != "" and not found:
+ os.write(tmp_fd, module_line)
+ found = True
+
+ if ctr == index:
+ within_title = 1
+ else:
+ within_title = 0
+ ctr = ctr + 1
+ elif within_title and self.module_re.match(line):
+ start = line.find("module")
+ l = line[start+6:len(line)]
+ l = l.lstrip()
+ if l[0] == '/':
+ prefix = "/"
+ else:
+ prefix = ""
+ prefix = get_prefix()
+ module_line = "\tmodule %s%s\n" % (prefix,binpolname)
+ else:
+ if module_line != "" and not found:
+ os.write(tmp_fd, module_line)
+ found = True
+
+ os.write(tmp_fd, line)
+
+ if module_line != "" and not found:
+ os.write(tmp_fd, module_line)
+ found = True
+
+ shutil.move(boot_file, boot_file+"_save")
+ shutil.copyfile(tmp_grub, boot_file)
+ os.close(tmp_fd)
+ try:
+ os.remove(tmp_grub)
+ except:
+ pass
+ finally:
+ self.__bootfile_lock.release()
+ return found
+
+
+ def rm_policy_from_boottitle(self, index, unamelist):
+ """ Remove a policy from the given title. A list of possible policies
+ must be given to detect what module to remove
+ """
+ found = False
+ ctr = 0
+ within_title = 0
+
+ prefix = get_prefix()
+ namelist = [prefix+name for name in unamelist]
+
+ try:
+ boot_file = self.__get_bootfile()
+ except:
+ return False
+ try:
+ self.__bootfile_lock.acquire()
+
+ grub_fd = open(boot_file)
+ (tmp_fd, tmp_grub) = tempfile.mkstemp()
+ for line in grub_fd:
+ omit_line = False
+ if self.title_re.match(line):
+ if ctr == index:
+ within_title = 1
+ else:
+ within_title = 0
+ ctr = ctr + 1
+ if within_title and self.module_re.match(line):
+ if self.policy_re.match(line):
+ start = line.find("module")
+ pol = line[start+6:len(line)]
+ pol = pol.lstrip().rstrip()
+ if pol in namelist:
+ omit_line = True
+ found = True
+ if not omit_line:
+ os.write(tmp_fd, line)
+ if found:
+ shutil.move(boot_file, boot_file+"_save")
+ shutil.copyfile(tmp_grub, boot_file)
+ os.close(tmp_fd)
+ try:
+ os.remove(tmp_grub)
+ except:
+ pass
+ finally:
+ self.__bootfile_lock.release()
+ return found
+
+
+ def set_kernel_attval(self, index, att, val):
+ """
+ Append an attribut/value pair to the kernel line.
+ @param index : The index of the title to modify
+ @param att : The attribute to add
+ @param val : The value to add. If no value or the special value
+ '<>' is given, then the attribute will be removed.
+ If an empty value is given, then only the attribute
+ is added in the format "att", otherwise "att=val"
+ is added.
+ """
+ found = False
+ ctr = 0
+ within_title = 0
+ try:
+ boot_file = self.__get_bootfile()
+ except:
+ False
+ try:
+ self.__bootfile_lock.acquire()
+
+ grub_fd = open(boot_file)
+ (tmp_fd, tmp_grub) = tempfile.mkstemp()
+ for line in grub_fd:
+ if self.title_re.match(line):
+ if ctr == index:
+ within_title = 1
+ else:
+ within_title = 0
+ ctr = ctr + 1
+ if within_title and self.kernel_re.match(line):
+ nitems = []
+ items = line.split(" ")
+ i = 0
+ while i < len(items):
+ el = items[i].split("=",1)
+ if el[0] != att:
+ nitems.append(items[i].rstrip("\n"))
+ i += 1
+ if val == "":
+ nitems.append("%s" % (att))
+ elif val != None and val != "<>":
+ nitems.append("%s=%s" % (att,val))
+ line = " ".join(nitems) + "\n"
+ os.write(tmp_fd, line)
+ shutil.move(boot_file, boot_file+"_save")
+ shutil.copyfile(tmp_grub, boot_file)
+ os.close(tmp_fd)
+ try:
+ os.remove(tmp_grub)
+ except:
+ pass
+ finally:
+ self.__bootfile_lock.release()
+ return found
+
+
+ def get_kernel_val(self, index, att):
+ """
+ Get an attribute's value from the kernel line.
+ @param index : The index of the title to get the attribute/value from
+ @param att : The attribute to read the value of
+ """
+ ctr = 0
+ within_title = 0
+ try:
+ boot_file = self.__get_bootfile()
+ except:
+ return None
+ try:
+ self.__bootfile_lock.acquire()
+
+ grub_fd = open(boot_file)
+ for line in grub_fd:
+ if self.title_re.match(line):
+ if ctr == index:
+ within_title = 1
+ else:
+ within_title = 0
+ ctr = ctr + 1
+ if within_title and self.kernel_re.match(line):
+ line = line.rstrip().lstrip()
+ items = line.split(" ")
+ i = 0
+ while i < len(items):
+ el = items[i].split("=",1)
+ if el[0] == att:
+ if len(el) == 1:
+ return "<>"
+ return el[1]
+ i += 1
+ finally:
+ self.__bootfile_lock.release()
+ return None # Not found
+
+
+__bootloader = Bootloader()
+
+grub = Grub()
+if grub.probe() == True:
+ __bootloader = grub
diff --git a/tools/python/xen/util/security.py b/tools/python/xen/util/security.py
index 2702fd3dbb..3cf58854ff 100644
--- a/tools/python/xen/util/security.py
+++ b/tools/python/xen/util/security.py
@@ -15,17 +15,22 @@
# Copyright (C) 2006 International Business Machines Corp.
# Author: Reiner Sailer
# Author: Bryan D. Payne <bdpayne@us.ibm.com>
+# Author: Stefan Berger <stefanb@us.ibm.com>
#============================================================================
import commands
import logging
-import sys, os, string, re
-import traceback
-import shutil
+import os, string, re
+import threading
+import struct
+import stat
from xen.lowlevel import acm
from xen.xend import sxp
+from xen.xend import XendConstants
from xen.xend.XendLogging import log
-from xen.util import dictio
+from xen.xend.XendError import VmError
+from xen.util import dictio, xsconstants
+from xen.xend.XendConstants import *
#global directories and tools for security management
policy_dir_prefix = "/etc/xen/acm-security/policies"
@@ -60,6 +65,10 @@ policy_name_re = re.compile(".*[chwall|ste|chwall_ste].*", re.IGNORECASE)
#other global variables
NULL_SSIDREF = 0
+#general Rlock for map files; only one lock for all mapfiles
+__mapfile_lock = threading.RLock()
+__resfile_lock = threading.RLock()
+
log = logging.getLogger("xend.util.security")
# Our own exception definition. It is masked (pass) if raised and
@@ -75,7 +84,6 @@ class ACMError(Exception):
def err(msg):
"""Raise ACM exception.
"""
- sys.stderr.write("ACMError: " + msg + "\n")
raise ACMError(msg)
@@ -83,6 +91,13 @@ def err(msg):
active_policy = None
+def mapfile_lock():
+ __mapfile_lock.acquire()
+
+def mapfile_unlock():
+ __mapfile_lock.release()
+
+
def refresh_security_policy():
"""
retrieves security policy
@@ -106,6 +121,39 @@ def on():
return (active_policy not in ['INACTIVE', 'NULL'])
+def calc_dom_ssidref_from_info(info):
+ """
+ Calculate a domain's ssidref from the security_label in its
+ info.
+ This function is called before the domain is started and
+ makes sure that:
+ - the type of the policy is the same as indicated in the label
+ - the name of the policy is the same as indicated in the label
+ - calculates an up-to-date ssidref for the domain
+ The latter is necessary since the domain's ssidref could have
+ changed due to changes to the policy.
+ """
+ import xen.xend.XendConfig
+ if isinstance(info, xen.xend.XendConfig.XendConfig):
+ if info.has_key('security_label'):
+ seclab = info['security_label']
+ tmp = seclab.split(":")
+ if len(tmp) != 3:
+ raise VmError("VM label '%s' in wrong format." % seclab)
+ typ, policyname, vmlabel = seclab.split(":")
+ if typ != xsconstants.ACM_POLICY_ID:
+ raise VmError("Policy type '%s' not supported." % typ)
+ refresh_security_policy()
+ if active_policy != policyname:
+ raise VmError("Active policy '%s' different than "
+ "what in VM's label ('%s')." %
+ (active_policy, policyname))
+ ssidref = label2ssidref(vmlabel, policyname, "dom")
+ return ssidref
+ else:
+ return 0
+ raise VmError("security.calc_dom_ssidref_from_info: info of type '%s'"
+ "not supported." % type(info))
# Assumes a 'security' info [security access_control ...] [ssidref ...]
def get_security_info(info, field):
@@ -146,7 +194,6 @@ def get_security_info(info, field):
return None
-
def get_security_printlabel(info):
"""retrieves printable security label from self.info['security']),
preferably the label name and otherwise (if label is not specified
@@ -250,32 +297,37 @@ def ssidref2label(ssidref_var):
else:
err("Instance type of ssidref not supported (must be of type 'str' or 'int')")
- (primary, secondary, f, pol_exists) = getmapfile(None)
- if not f:
- if (pol_exists):
- err("Mapping file for policy \'" + policyname + "\' not found.\n" +
- "Please use makepolicy command to create mapping file!")
- else:
- err("Policy file for \'" + active_policy + "\' not found.")
-
- #2. get labelnames for both ssidref parts
- pri_ssid = ssidref & 0xffff
- sec_ssid = ssidref >> 16
- pri_null_ssid = NULL_SSIDREF & 0xffff
- sec_null_ssid = NULL_SSIDREF >> 16
- pri_labels = []
- sec_labels = []
- labels = []
+ try:
+ mapfile_lock()
- for line in f:
- l = line.split()
- if (len(l) < 5) or (l[0] != "LABEL->SSID"):
- continue
- if primary and (l[2] == primary) and (int(l[4], 16) == pri_ssid):
- pri_labels.append(l[3])
- if secondary and (l[2] == secondary) and (int(l[4], 16) == sec_ssid):
- sec_labels.append(l[3])
- f.close()
+ (primary, secondary, f, pol_exists) = getmapfile(None)
+ if not f:
+ if (pol_exists):
+ err("Mapping file for policy not found.\n" +
+ "Please use makepolicy command to create mapping file!")
+ else:
+ err("Policy file for \'" + active_policy + "\' not found.")
+
+ #2. get labelnames for both ssidref parts
+ pri_ssid = ssidref & 0xffff
+ sec_ssid = ssidref >> 16
+ pri_null_ssid = NULL_SSIDREF & 0xffff
+ sec_null_ssid = NULL_SSIDREF >> 16
+ pri_labels = []
+ sec_labels = []
+ labels = []
+
+ for line in f:
+ l = line.split()
+ if (len(l) < 5) or (l[0] != "LABEL->SSID"):
+ continue
+ if primary and (l[2] == primary) and (int(l[4], 16) == pri_ssid):
+ pri_labels.append(l[3])
+ if secondary and (l[2] == secondary) and (int(l[4], 16) == sec_ssid):
+ sec_labels.append(l[3])
+ f.close()
+ finally:
+ mapfile_unlock()
#3. get the label that is in both lists (combination must be a single label)
if (primary == "CHWALL") and (pri_ssid == pri_null_ssid) and (sec_ssid != sec_null_ssid):
@@ -297,7 +349,7 @@ def ssidref2label(ssidref_var):
-def label2ssidref(labelname, policyname, type):
+def label2ssidref(labelname, policyname, typ):
"""
returns ssidref corresponding to labelname;
maps current policy to default directory
@@ -307,42 +359,51 @@ def label2ssidref(labelname, policyname, type):
err("Cannot translate labels for \'" + policyname + "\' policy.")
allowed_types = ['ANY']
- if type == 'dom':
+ if typ == 'dom':
allowed_types.append('VM')
- elif type == 'res':
+ elif typ == 'res':
allowed_types.append('RES')
else:
err("Invalid type. Must specify 'dom' or 'res'.")
- (primary, secondary, f, pol_exists) = getmapfile(policyname)
-
- #2. get labelnames for ssidref parts and find a common label
- pri_ssid = []
- sec_ssid = []
- for line in f:
- l = line.split()
- if (len(l) < 5) or (l[0] != "LABEL->SSID"):
- continue
- if primary and (l[1] in allowed_types) and (l[2] == primary) and (l[3] == labelname):
- pri_ssid.append(int(l[4], 16))
- if secondary and (l[1] in allowed_types) and (l[2] == secondary) and (l[3] == labelname):
- sec_ssid.append(int(l[4], 16))
- f.close()
- if (type == 'res') and (primary == "CHWALL") and (len(pri_ssid) == 0):
- pri_ssid.append(NULL_SSIDREF)
- elif (type == 'res') and (secondary == "CHWALL") and (len(sec_ssid) == 0):
- sec_ssid.append(NULL_SSIDREF)
-
- #3. sanity check and composition of ssidref
- if (len(pri_ssid) == 0) or ((len(sec_ssid) == 0) and (secondary != "NULL")):
- err("Label \'" + labelname + "\' not found.")
- elif (len(pri_ssid) > 1) or (len(sec_ssid) > 1):
- err("Label \'" + labelname + "\' not unique in policy (policy error)")
- if secondary == "NULL":
- return pri_ssid[0]
- else:
- return (sec_ssid[0] << 16) | pri_ssid[0]
+ try:
+ mapfile_lock()
+ (primary, secondary, f, pol_exists) = getmapfile(policyname)
+ #2. get labelnames for ssidref parts and find a common label
+ pri_ssid = []
+ sec_ssid = []
+ for line in f:
+ l = line.split()
+ if (len(l) < 5) or (l[0] != "LABEL->SSID"):
+ continue
+ if primary and (l[1] in allowed_types) and \
+ (l[2] == primary) and \
+ (l[3] == labelname):
+ pri_ssid.append(int(l[4], 16))
+ if secondary and (l[1] in allowed_types) and \
+ (l[2] == secondary) and \
+ (l[3] == labelname):
+ sec_ssid.append(int(l[4], 16))
+ f.close()
+ if (typ == 'res') and (primary == "CHWALL") and (len(pri_ssid) == 0):
+ pri_ssid.append(NULL_SSIDREF)
+ elif (typ == 'res') and (secondary == "CHWALL") and \
+ (len(sec_ssid) == 0):
+ sec_ssid.append(NULL_SSIDREF)
+
+ #3. sanity check and composition of ssidref
+ if (len(pri_ssid) == 0) or ((len(sec_ssid) == 0) and \
+ (secondary != "NULL")):
+ err("Label \'" + labelname + "\' not found.")
+ elif (len(pri_ssid) > 1) or (len(sec_ssid) > 1):
+ err("Label \'" + labelname + "\' not unique in policy (policy error)")
+ if secondary == "NULL":
+ return pri_ssid[0]
+ else:
+ return (sec_ssid[0] << 16) | pri_ssid[0]
+ finally:
+ mapfile_unlock()
def refresh_ssidref(config):
@@ -381,8 +442,9 @@ def refresh_ssidref(config):
err("Illegal field in access_control")
#verify policy is correct
if active_policy != policyname:
- err("Policy \'" + policyname + "\' in label does not match active policy \'"
- + active_policy +"\'!")
+ err("Policy \'" + str(policyname) +
+ "\' in label does not match active policy \'"
+ + str(active_policy) +"\'!")
new_ssidref = label2ssidref(labelname, policyname, 'dom')
if not new_ssidref:
@@ -470,6 +532,25 @@ def get_decision(arg1, arg2):
err("Cannot determine decision (Invalid parameter).")
+def hv_chg_policy(bin_pol, del_array, chg_array):
+ """
+ Change the binary policy in the hypervisor
+ The 'del_array' and 'chg_array' give hints about deleted ssidrefs
+ and changed ssidrefs which can be due to deleted VM labels
+ or reordered VM labels
+ """
+ rc = -xsconstants.XSERR_GENERAL_FAILURE
+ errors = ""
+ if not on():
+ err("No policy active.")
+ try:
+ rc, errors = acm.chgpolicy(bin_pol, del_array, chg_array)
+ except Exception, e:
+ pass
+ if (len(errors) > 0):
+ rc = -xsconstants.XSERR_HV_OP_FAILED
+ return rc, errors
+
def make_policy(policy_name):
policy_file = string.join(string.split(policy_name, "."), "/")
@@ -480,8 +561,6 @@ def make_policy(policy_name):
if ret:
err("Creating policy failed:\n" + output)
-
-
def load_policy(policy_name):
global active_policy
policy_file = policy_dir_prefix + "/" + string.join(string.split(policy_name, "."), "/")
@@ -538,8 +617,8 @@ def list_labels(policy_name, condition):
def get_res_label(resource):
- """Returns resource label information (label, policy) if it exists.
- Otherwise returns null label and policy.
+ """Returns resource label information (policytype, label, policy) if
+ it exists. Otherwise returns null label and policy.
"""
def default_res_label():
ssidref = NULL_SSIDREF
@@ -547,23 +626,19 @@ def get_res_label(resource):
label = ssidref2label(ssidref)
else:
label = None
- return (label, 'NULL')
+ return (xsconstants.ACM_POLICY_ID, 'NULL', label)
- (label, policy) = default_res_label()
- # load the resource label file
- res_label_cache = {}
- try:
- res_label_cache = dictio.dict_read("resources", res_label_filename)
- except:
- log.info("Resource label file not found.")
- return default_res_label()
-
- # find the resource information
- if res_label_cache.has_key(resource):
- (policy, label) = res_label_cache[resource]
+ tmp = get_resource_label(resource)
+ if len(tmp) == 2:
+ policytype = xsconstants.ACM_POLICY_ID
+ policy, label = tmp
+ elif len(tmp) == 3:
+ policytype, policy, label = tmp
+ else:
+ policytype, policy, label = default_res_label()
- return (label, policy)
+ return (policytype, label, policy)
def get_res_security_details(resource):
@@ -582,7 +657,7 @@ def get_res_security_details(resource):
(label, ssidref, policy) = default_security_details()
# find the entry associated with this resource
- (label, policy) = get_res_label(resource)
+ (policytype, label, policy) = get_res_label(resource)
if policy == 'NULL':
log.info("Resource label for "+resource+" not in file, using DEFAULT.")
return default_security_details()
@@ -596,8 +671,29 @@ def get_res_security_details(resource):
return (label, ssidref, policy)
+def security_label_to_details(seclab):
+ """ Convert a Xen-API type of security label into details """
+ def default_security_details():
+ ssidref = NULL_SSIDREF
+ if on():
+ label = ssidref2label(ssidref)
+ else:
+ label = None
+ policy = active_policy
+ return (label, ssidref, policy)
+
+ (policytype, policy, label) = seclab.split(":")
+
+ # is this resource label for the running policy?
+ if policy == active_policy:
+ ssidref = label2ssidref(label, policy, 'res')
+ else:
+ log.info("Resource label not for active policy, using DEFAULT.")
+ return default_security_details()
-def unify_resname(resource):
+ return (label, ssidref, policy)
+
+def unify_resname(resource, mustexist=True):
"""Makes all resource locations absolute. In case of physical
resources, '/dev/' is added to local file names"""
@@ -606,28 +702,53 @@ def unify_resname(resource):
# sanity check on resource name
try:
- (type, resfile) = resource.split(":", 1)
+ (typ, resfile) = resource.split(":", 1)
except:
err("Resource spec '%s' contains no ':' delimiter" % resource)
- if type == "tap":
+ if typ == "tap":
try:
(subtype, resfile) = resfile.split(":")
except:
err("Resource spec '%s' contains no tap subtype" % resource)
- if type in ["phy", "tap"]:
+ import os
+ if typ in ["phy", "tap"]:
if not resfile.startswith("/"):
resfile = "/dev/" + resfile
+ if mustexist:
+ stats = os.lstat(resfile)
+ if stat.S_ISLNK(stats[stat.ST_MODE]):
+ resolved = os.readlink(resfile)
+ if resolved[0] != "/":
+ resfile = os.path.join(os.path.dirname(resfile), resolved)
+ resfile = os.path.abspath(resfile)
+ else:
+ resfile = resolved
+ stats = os.lstat(resfile)
+ if not (stat.S_ISBLK(stats[stat.ST_MODE])):
+ err("Invalid resource")
+
+ if typ in [ "file", "tap" ]:
+ if mustexist:
+ stats = os.lstat(resfile)
+ if stat.S_ISLNK(stats[stat.ST_MODE]):
+ resfile = os.readlink(resfile)
+ stats = os.lstat(resfile)
+ if not stat.S_ISREG(stats[stat.ST_MODE]):
+ err("Invalid resource")
#file: resources must specified with absolute path
- if (not resfile.startswith("/")) or (not os.path.exists(resfile)):
- err("Invalid resource.")
+ #vlan resources don't start with '/'
+ if typ != "vlan":
+ if (not resfile.startswith("/")) or \
+ (mustexist and not os.path.exists(resfile)):
+ err("Invalid resource.")
# from here on absolute file names with resources
- if type == "tap":
- type = type + ":" + subtype
- resource = type + ":" + resfile
+ if typ == "tap":
+ typ = typ + ":" + subtype
+ resource = typ + ":" + resfile
return resource
@@ -662,9 +783,481 @@ def res_security_check(resource, domain_label):
else:
# Note, we can't canonicalise the resource here, because people using
# xm without ACM are free to use relative paths.
- (label, policy) = get_res_label(resource)
+ (policytype, label, policy) = get_res_label(resource)
if policy != 'NULL':
raise ACMError("Security is off, but '"+resource+"' is labeled")
rtnval = 0
return rtnval
+
+def res_security_check_xapi(rlabel, rssidref, rpolicy, xapi_dom_label):
+ """Checks if the given resource can be used by the given domain
+ label. Returns 1 if the resource can be used, otherwise 0.
+ """
+ rtnval = 1
+ # if security is on, ask the hypervisor for a decision
+ if on():
+ typ, dpolicy, domain_label = xapi_dom_label.split(":")
+ if not dpolicy or not domain_label:
+ raise VmError("VM security label in wrong format.")
+ if active_policy != rpolicy:
+ raise VmError("Resource's policy '%s' != active policy '%s'" %
+ (rpolicy, active_policy))
+ domac = ['access_control']
+ domac.append(['policy', active_policy])
+ domac.append(['label', domain_label])
+ domac.append(['type', 'dom'])
+ decision = get_decision(domac, ['ssidref', str(rssidref)])
+
+ log.info("Access Control Decision : %s" % decision)
+ # provide descriptive error messages
+ if decision == 'DENIED':
+ if rlabel == ssidref2label(NULL_SSIDREF):
+ #raise ACMError("Resource is not labeled")
+ rtnval = 0
+ else:
+ #raise ACMError("Permission denied for resource because label '"+rlabel+"' is not allowed")
+ rtnval = 0
+
+ # security is off, make sure resource isn't labeled
+ else:
+ # Note, we can't canonicalise the resource here, because people using
+ # xm without ACM are free to use relative paths.
+ if rpolicy != 'NULL':
+ #raise ACMError("Security is off, but resource is labeled")
+ rtnval = 0
+
+ return rtnval
+
+
+def set_resource_label_xapi(resource, reslabel_xapi, oldlabel_xapi):
+ """Assign a resource label to a resource
+ @param resource: The name of a resource, i.e., "phy:/dev/hda", or
+ "tap:qcow:/path/to/file.qcow"
+
+ @param reslabel_xapi: A resource label foramtted as in all other parts of
+ the Xen-API, i.e., ACM:xm-test:blue"
+ @rtype: int
+ @return Success (0) or failure value (< 0)
+ """
+ olabel = ""
+ if reslabel_xapi == "":
+ return rm_resource_label(resource, oldlabel_xapi)
+ typ, policyref, label = reslabel_xapi.split(":")
+ if typ != xsconstants.ACM_POLICY_ID:
+ return -xsconstants.XSERR_WRONG_POLICY_TYPE
+ if not policyref or not label:
+ return -xsconstants.XSERR_BAD_LABEL_FORMAT
+ if oldlabel_xapi not in [ "" ]:
+ tmp = oldlabel_xapi.split(":")
+ if len(tmp) != 3:
+ return -xsconstants.XSERR_BAD_LABEL_FORMAT
+ otyp, opolicyref, olabel = tmp
+ # Only ACM is supported
+ if otyp != xsconstants.ACM_POLICY_ID:
+ return -xsconstants.XSERR_WRONG_POLICY_TYPE
+ return set_resource_label(resource, typ, policyref, label, olabel)
+
+def is_resource_in_use(resource):
+ """ Investigate all running domains whether they use this device """
+ from xen.xend import XendDomain
+ dominfos = XendDomain.instance().list('all')
+ lst = []
+ for dominfo in dominfos:
+ if is_resource_in_use_by_dom(dominfo, resource):
+ lst.append(dominfo)
+ return lst
+
+def devices_equal(res1, res2):
+ """ Determine whether two devices are equal """
+ return (unify_resname(res1) == unify_resname(res2))
+
+def is_resource_in_use_by_dom(dominfo, resource):
+ """ Determine whether a resources is in use by a given domain
+ @return True or False
+ """
+ if not dominfo.domid:
+ return False
+ if dominfo._stateGet() not in [ DOM_STATE_RUNNING ]:
+ return False
+ devs = dominfo.info['devices']
+ uuids = devs.keys()
+ for uuid in uuids:
+ dev = devs[uuid]
+ if len(dev) >= 2 and dev[1].has_key('uname'):
+ # dev[0] is type, i.e. 'vbd'
+ if devices_equal(dev[1]['uname'], resource):
+ log.info("RESOURCE IN USE: Domain %d uses %s." %
+ (dominfo.domid, resource))
+ return True
+ return False
+
+
+def get_domain_resources(dominfo):
+ """ Collect all resources of a domain in a map where each entry of
+ the map is a list.
+ Entries are strored in the following formats:
+ tap:qcow:/path/xyz.qcow
+ """
+ resources = { 'vbd' : [], 'tap' : []}
+ devs = dominfo.info['devices']
+ uuids = devs.keys()
+ for uuid in uuids:
+ dev = devs[uuid]
+ typ = dev[0]
+ if typ in [ 'vbd', 'tap' ]:
+ resources[typ].append(dev[1]['uname'])
+
+ return resources
+
+
+def resources_compatible_with_vmlabel(xspol, dominfo, vmlabel):
+ """
+ Check whether the resources' labels are compatible with the
+ given VM label. This is a function to be used when for example
+ a running domain is to get the new label 'vmlabel'
+ """
+ if not xspol:
+ return False
+
+ try:
+ __resfile_lock.acquire()
+ try:
+ access_control = dictio.dict_read("resources",
+ res_label_filename)
+ except:
+ return False
+ return __resources_compatible_with_vmlabel(xspol, dominfo, vmlabel,
+ access_control)
+ finally:
+ __resfile_lock.release()
+ return False
+
+
+def __resources_compatible_with_vmlabel(xspol, dominfo, vmlabel,
+ access_control):
+ """
+ Check whether the resources' labels are compatible with the
+ given VM label. The access_control parameter provides a
+ dictionary of the resource name to resource label mappings
+ under which the evaluation should be done.
+ """
+ resources = get_domain_resources(dominfo)
+ reslabels = [] # all resource labels
+ polname = xspol.get_name()
+ for key in resources.keys():
+ for res in resources[key]:
+ try:
+ tmp = access_control[res]
+ if len(tmp) != 3:
+ return False
+
+ if polname != tmp[1]:
+ return False
+ label = tmp[2]
+ if not label in reslabels:
+ reslabels.append(label)
+ except:
+ return False
+ # Check that all resource labes have a common STE type with the
+ # vmlabel
+ rc = xspol.policy_check_vmlabel_against_reslabels(vmlabel, reslabels)
+ return rc;
+
+def set_resource_label(resource, policytype, policyref, reslabel, \
+ oreslabel = None):
+ """Assign a label to a resource
+ If the old label (oreslabel) is given, then the resource must have
+ that old label.
+ A resource label may be changed if
+ - the resource is not in use
+ @param resource : The name of a resource, i.e., "phy:/dev/hda"
+ @param policyref : The name of the policy
+ @param reslabel : the resource label within the policy
+ @param oreslabel : optional current resource label
+
+ @rtype: int
+ @return Success (0) or failure value (< 0)
+ """
+ try:
+ resource = unify_resname(resource, mustexist=False)
+ except Exception:
+ return -xsconstants.XSERR_BAD_RESOURCE_FORMAT
+
+ domains = is_resource_in_use(resource)
+ if len(domains) > 0:
+ return -xsconstants.XSERR_RESOURCE_IN_USE
+
+ try:
+ __resfile_lock.acquire()
+ access_control = {}
+ try:
+ access_control = dictio.dict_read("resources", res_label_filename)
+ except:
+ pass
+ if oreslabel:
+ if not access_control.has_key(resource):
+ return -xsconstants.XSERR_BAD_LABEL
+ tmp = access_control[resource]
+ if len(tmp) != 3:
+ return -xsconstants.XSERR_BAD_LABEL
+ if tmp[2] != oreslabel:
+ return -xsconstants.XSERR_BAD_LABEL
+ if reslabel != "":
+ new_entry = { resource : tuple([policytype, policyref, reslabel])}
+ access_control.update(new_entry)
+ else:
+ if access_control.has_key(resource):
+ del access_control[resource]
+ dictio.dict_write(access_control, "resources", res_label_filename)
+ finally:
+ __resfile_lock.release()
+ return xsconstants.XSERR_SUCCESS
+
+def rm_resource_label(resource, oldlabel_xapi):
+ """Remove a resource label from a physical resource
+ @param resource: The name of a resource, i.e., "phy:/dev/hda"
+
+ @rtype: int
+ @return Success (0) or failure value (< 0)
+ """
+ tmp = oldlabel_xapi.split(":")
+ if len(tmp) != 3:
+ return -xsconstants.XSERR_BAD_LABEL_FORMAT
+ otyp, opolicyref, olabel = tmp
+ # Only ACM is supported
+ if otyp != xsconstants.ACM_POLICY_ID and \
+ otyp != xsconstants.INVALID_POLICY_PREFIX + xsconstants.ACM_POLICY_ID:
+ return -xsconstants.XSERR_WRONG_POLICY_TYPE
+ return set_resource_label(resource, "", "", "", olabel)
+
+def get_resource_label_xapi(resource):
+ """Get the assigned resource label of a physical resource
+ in the format used by then Xen-API, i.e., "ACM:xm-test:blue"
+
+ @rtype: string
+ @return the string representing policy type, policy name and label of
+ the resource
+ """
+ res = get_resource_label(resource)
+ return format_resource_label(res)
+
+def format_resource_label(res):
+ if res:
+ if len(res) == 2:
+ return xsconstants.ACM_POLICY_ID + ":" + res[0] + ":" + res[1]
+ if len(res) == 3:
+ return ":".join(res)
+ return ""
+
+def get_resource_label(resource):
+ """Get the assigned resource label of a given resource
+ @param resource: The name of a resource, i.e., "phy:/dev/hda"
+
+ @rtype: list
+ @return tuple of (policy name, resource label), i.e., (xm-test, blue)
+ """
+ try:
+ resource = unify_resname(resource, mustexist=False)
+ except Exception:
+ return []
+
+ reslabel_map = get_labeled_resources()
+
+ if reslabel_map.has_key(resource):
+ return list(reslabel_map[resource])
+ else:
+ #Try to resolve each label entry
+ for key, value in reslabel_map.items():
+ try:
+ if resource == unify_resname(key):
+ return list(value)
+ except:
+ pass
+
+ return []
+
+
+def get_labeled_resources_xapi():
+ """ Get a map of all labeled resource with the labels formatted in the
+ xen-api resource label format.
+ """
+ reslabel_map = get_labeled_resources()
+ for key, labeldata in reslabel_map.items():
+ reslabel_map[key] = format_resource_label(labeldata)
+ return reslabel_map
+
+
+def get_labeled_resources():
+ """Get a map of all labeled resources
+ @rtype: list
+ @return list of labeled resources
+ """
+ try:
+ __resfile_lock.acquire()
+ try:
+ access_control = dictio.dict_read("resources", res_label_filename)
+ except:
+ return {}
+ finally:
+ __resfile_lock.release()
+ return access_control
+
+
+def relabel_domains(relabel_list):
+ """
+ Relabel the given domains to have a new ssidref.
+ @param relabel_list: a list containing tuples of domid, ssidref
+ example: [ [0, 0x00020002] ]
+ """
+ rel_rules = ""
+ for r in relabel_list:
+ log.info("Relabeling domain with domid %d to new ssidref 0x%08x",
+ r[0], r[1])
+ rel_rules += struct.pack("ii", r[0], r[1])
+ try:
+ rc, errors = acm.relabel_domains(rel_rules)
+ except Exception, e:
+ log.info("Error after relabel_domains: %s" % str(e))
+ rc = -xsconstants.XSERR_GENERAL_FAILURE
+ errors = ""
+ if (len(errors) > 0):
+ rc = -xsconstants.XSERR_HV_OP_FAILED
+ return rc, errors
+
+
+def change_acm_policy(bin_pol, del_array, chg_array,
+ vmlabel_map, reslabel_map, cur_acmpol, new_acmpol):
+ """
+ Change the ACM policy of the system by relabeling
+ domains and resources first and doing some access checks.
+ Then update the policy in the hypervisor. If this is all successful,
+ relabel the domains permanently and commit the relabed resources.
+
+ Need to do / check the following:
+ - relabel all resources where there is a 'from' field in
+ the policy. [ NOT DOING THIS: and mark those as unlabeled where the label
+ does not appear in the new policy anymore (deletion) ]
+ - relabel all VMs where there is a 'from' field in the
+ policy and mark those as unlabeled where the label
+ does not appear in the new policy anymore; no running
+ or paused VM may be unlabeled through this
+ - check that under the new labeling conditions the VMs
+ still have access to their resources as before. Unlabeled
+ resources are inaccessible. If this check fails, the
+ update failed.
+ - Attempt changes in the hypervisor; if this step fails,
+ roll back the relabeling of resources and VMs
+ - Make the relabeling of resources and VMs permanent
+ """
+ rc = xsconstants.XSERR_SUCCESS
+
+ domain_label_map = {}
+ new_policyname = new_acmpol.get_name()
+ new_policytype = new_acmpol.get_type_name()
+ cur_policyname = cur_acmpol.get_name()
+ cur_policytype = cur_acmpol.get_type_name()
+ polnew_reslabels = new_acmpol.policy_get_resourcelabel_names()
+ errors=""
+
+ try:
+ __resfile_lock.acquire()
+ mapfile_lock()
+
+ # Get all domains' dominfo.
+ from xen.xend import XendDomain
+ dominfos = XendDomain.instance().list('all')
+
+ log.info("----------------------------------------------")
+ # relabel resources
+
+ access_control = {}
+ try:
+ access_control = dictio.dict_read("resources", res_label_filename)
+ finally:
+ pass
+ for key, labeldata in access_control.items():
+ if len(labeldata) == 2:
+ policy, label = labeldata
+ policytype = xsconstants.ACM_POLICY_ID
+ elif len(labeldata) == 3:
+ policytype, policy, label = labeldata
+ else:
+ return -xsconstants.XSERR_BAD_LABEL_FORMAT, ""
+
+ if policytype != cur_policytype or \
+ policy != cur_policyname:
+ continue
+
+ # label been renamed or deleted?
+ if reslabel_map.has_key(label) and cur_policyname == policy:
+ label = reslabel_map[label]
+ elif label not in polnew_reslabels:
+ policytype = xsconstants.INVALID_POLICY_PREFIX + policytype
+ # Update entry
+ access_control[key] = \
+ tuple([ policytype, new_policyname, label ])
+
+ # All resources have new labels in the access_control map
+ # There may still be labels in there that are invalid now.
+
+ # Do this in memory without writing to disk:
+ # - Relabel all domains independent of whether they are running
+ # or not
+ # - later write back to config files
+ polnew_vmlabels = new_acmpol.policy_get_virtualmachinelabel_names()
+
+ for dominfo in dominfos:
+ sec_lab = dominfo.get_security_label()
+ if not sec_lab:
+ continue
+ policytype, policy, vmlabel = sec_lab.split(":")
+ name = dominfo.getName()
+
+ if policytype != cur_policytype or \
+ policy != cur_policyname:
+ continue
+
+ new_vmlabel = vmlabel
+ if vmlabel_map.has_key(vmlabel):
+ new_vmlabel = vmlabel_map[vmlabel]
+ if new_vmlabel not in polnew_vmlabels:
+ policytype = xsconstants.INVALID_POLICY_PREFIX + policytype
+ new_seclab = "%s:%s:%s" % \
+ (policytype, new_policyname, new_vmlabel)
+
+ domain_label_map[dominfo] = [ sec_lab, new_seclab ]
+
+ if dominfo._stateGet() in (DOM_STATE_PAUSED, DOM_STATE_RUNNING):
+ compatible = __resources_compatible_with_vmlabel(new_acmpol,
+ dominfo,
+ new_vmlabel,
+ access_control)
+ log.info("Domain %s with new label '%s' can access its "
+ "resources? : %s" %
+ (name, new_vmlabel, str(compatible)))
+ log.info("VM labels in new domain: %s" %
+ new_acmpol.policy_get_virtualmachinelabel_names())
+ if not compatible:
+ return (-xsconstants.XSERR_RESOURCE_ACCESS, "")
+
+ rc, errors = hv_chg_policy(bin_pol, del_array, chg_array)
+ if rc == 0:
+ # Write the relabeled resources back into the file
+ dictio.dict_write(access_control, "resources", res_label_filename)
+ # Properly update all VMs to their new labels
+ for dominfo, labels in domain_label_map.items():
+ sec_lab, new_seclab = labels
+ if sec_lab != new_seclab:
+ log.info("Updating domain %s to new label '%s'." % \
+ (new_seclab, sec_lab))
+ # This better be working!
+ dominfo.set_security_label(new_seclab,
+ sec_lab,
+ new_acmpol)
+ finally:
+ log.info("----------------------------------------------")
+ mapfile_unlock()
+ __resfile_lock.release()
+
+ return rc, errors
diff --git a/tools/python/xen/util/xsconstants.py b/tools/python/xen/util/xsconstants.py
new file mode 100644
index 0000000000..856ef43aca
--- /dev/null
+++ b/tools/python/xen/util/xsconstants.py
@@ -0,0 +1,104 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#============================================================================
+# Copyright (C) 2007 International Business Machines Corp.
+# Author: Stefan Berger <stefanb@us.ibm.com>
+#============================================================================
+
+XS_INST_NONE = 0
+XS_INST_BOOT = (1 << 0)
+XS_INST_LOAD = (1 << 1)
+
+XS_POLICY_NONE = 0
+XS_POLICY_ACM = (1 << 0)
+
+# Some internal variables used by the Xen-API
+ACM_LABEL_VM = (1 << 0)
+ACM_LABEL_RES = (1 << 1)
+
+# Base for XS error codes for collision avoidance with other error codes
+XSERR_BASE = 0x1000
+
+# XS error codes as used by the Xen-API
+XSERR_SUCCESS = 0
+XSERR_GENERAL_FAILURE = 1 + XSERR_BASE
+XSERR_BAD_XML = 2 + XSERR_BASE # XML is wrong (not according to schema)
+XSERR_XML_PROCESSING = 3 + XSERR_BASE
+XSERR_POLICY_INCONSISTENT = 4 + XSERR_BASE # i.e., bootstrap name not a VM label
+XSERR_FILE_ERROR = 5 + XSERR_BASE
+XSERR_BAD_RESOURCE_FORMAT = 6 + XSERR_BASE # badly formatted resource
+XSERR_BAD_LABEL_FORMAT = 7 + XSERR_BASE
+XSERR_RESOURCE_NOT_LABELED = 8 + XSERR_BASE
+XSERR_RESOURCE_ALREADY_LABELED = 9 + XSERR_BASE
+XSERR_WRONG_POLICY_TYPE = 10 + XSERR_BASE
+XSERR_BOOTPOLICY_INSTALLED = 11 + XSERR_BASE
+XSERR_NO_DEFAULT_BOOT_TITLE = 12 + XSERR_BASE
+XSERR_POLICY_LOAD_FAILED = 13 + XSERR_BASE
+XSERR_POLICY_LOADED = 14 + XSERR_BASE
+XSERR_POLICY_TYPE_UNSUPPORTED = 15 + XSERR_BASE
+XSERR_BAD_CONFLICTSET = 16 + XSERR_BASE
+XSERR_RESOURCE_IN_USE = 17 + XSERR_BASE
+XSERR_BAD_POLICY_NAME = 18 + XSERR_BASE
+XSERR_VERSION_PREVENTS_UPDATE = 19 + XSERR_BASE
+XSERR_BAD_LABEL = 20 + XSERR_BASE
+XSERR_VM_WRONG_STATE = 21 + XSERR_BASE
+XSERR_POLICY_NOT_LOADED = 22 + XSERR_BASE
+XSERR_RESOURCE_ACCESS = 23 + XSERR_BASE
+XSERR_HV_OP_FAILED = 24 + XSERR_BASE
+XSERR_BOOTPOLICY_INSTALL_ERROR = 25 + XSERR_BASE
+XSERR_LAST = 25 + XSERR_BASE ## KEEP LAST
+
+XSERR_MESSAGES = [
+ '',
+ 'General Failure',
+ 'XML is malformed',
+ 'Error while processing XML',
+ 'Policy has inconsistencies',
+ 'A file access error occurred',
+ 'The resource format is not valid',
+ 'The label format is not valid',
+ 'The resource is not labeld',
+ 'The resource is already labeld',
+ 'The policy type is wrong',
+ 'The system boot policy is installed',
+ 'Could not find the default boot title',
+ 'Loading of the policy failed',
+ 'The policy is loaded',
+ 'The policy type is unsupported',
+ 'There is a bad conflict set',
+ 'The resource is in use',
+ 'The policy has an invalid name',
+ 'The version of the policy prevents an update',
+ 'The label is bad',
+ 'Operation not premittend - the VM is in the wrong state',
+ 'The policy is not loaded',
+ 'Error accessing resource',
+ 'Operation failed in hypervisor',
+ 'Boot policy installation error'
+]
+
+def xserr2string(err):
+ if err == XSERR_SUCCESS:
+ return "Success"
+ if err >= XSERR_GENERAL_FAILURE and \
+ err <= XSERR_LAST:
+ return XSERR_MESSAGES[err - XSERR_BASE]
+ return "Unknown XSERR code '%s'." % (hex(err))
+
+# Policy identifiers used in labels
+ACM_POLICY_ID = "ACM"
+
+INVALID_POLICY_PREFIX = "INV_"
+
+INVALID_SSIDREF = 0xFFFFFFFF
diff --git a/tools/python/xen/util/xspolicy.py b/tools/python/xen/util/xspolicy.py
new file mode 100644
index 0000000000..7cd5656dad
--- /dev/null
+++ b/tools/python/xen/util/xspolicy.py
@@ -0,0 +1,66 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#============================================================================
+# Copyright (C) 2006,2007 International Business Machines Corp.
+# Author: Stefan Berger <stefanb@us.ibm.com>
+#============================================================================
+
+import threading
+import xsconstants
+
+class XSPolicy:
+ """
+ The base policy class for all policies administered through
+ XSPolicyAdmin.
+ """
+
+ def __init__(self, name=None, ref=None):
+ self.lock = threading.Lock()
+ self.ref = ref
+ self.name = name
+ if ref:
+ from xen.xend.XendXSPolicy import XendXSPolicy
+ self.xendxspolicy = XendXSPolicy(self, {}, ref)
+ else:
+ self.xendxspolicy = None
+
+ def grab_lock(self):
+ self.lock.acquire()
+
+ def unlock(self):
+ self.lock.release()
+
+ def get_ref(self):
+ return self.ref
+
+ def destroy(self):
+ if self.xendxspolicy:
+ self.xendxspolicy.destroy()
+
+ # All methods below should be overwritten by the inheriting class
+
+ def isloaded(self):
+ return False
+
+ def loadintohv(self):
+ return xsconstants.XSERR_POLICY_LOAD_FAILED
+
+ def get_type(self):
+ return xsconstants.XS_POLICY_NONE
+
+ def get_type_name(self):
+ return ""
+
+ def update(self, repr_new):
+ return -xsconstants.XSERR_GENERAL_FAILURE, ""
diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py
index 641ca944e5..7c33545492 100644
--- a/tools/python/xen/xend/XendAPI.py
+++ b/tools/python/xen/xend/XendAPI.py
@@ -40,11 +40,13 @@ from XendPIFMetrics import XendPIFMetrics
from XendVMMetrics import XendVMMetrics
from XendPIF import XendPIF
from XendPBD import XendPBD
+from XendXSPolicy import XendXSPolicy, XendACMPolicy
from XendAPIConstants import *
from xen.util.xmlrpclib2 import stringify
from xen.util.blkif import blkdev_name_to_number
+from xen.util import xsconstants
AUTH_NONE = 'none'
@@ -467,6 +469,8 @@ classes = {
'console' : valid_console,
'SR' : valid_sr,
'task' : valid_task,
+ 'XSPolicy' : valid_object("XSPolicy"),
+ 'ACMPolicy' : valid_object("ACMPolicy"),
'debug' : valid_debug,
'network' : valid_object("network"),
'PIF' : valid_object("PIF"),
@@ -481,6 +485,8 @@ autoplug_classes = {
'VM_metrics' : XendVMMetrics,
'PBD' : XendPBD,
'PIF_metrics' : XendPIFMetrics,
+ 'XSPolicy' : XendXSPolicy,
+ 'ACMPolicy' : XendACMPolicy,
}
class XendAPI(object):
@@ -1170,7 +1176,8 @@ class XendAPI(object):
'HVM_boot_params',
'platform',
'PCI_bus',
- 'other_config']
+ 'other_config',
+ 'security_label']
VM_methods = [('clone', 'VM'),
('start', None),
@@ -1230,7 +1237,8 @@ class XendAPI(object):
'HVM_boot_params',
'platform',
'PCI_bus',
- 'other_config']
+ 'other_config',
+ 'security_label']
def VM_get(self, name, session, vm_ref):
return xen_api_success(
@@ -1601,7 +1609,22 @@ class XendAPI(object):
if dom:
return xen_api_success([dom.get_uuid()])
return xen_api_success([])
-
+
+ def VM_get_security_label(self, session, vm_ref):
+ dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
+ label = dom.get_security_label()
+ return xen_api_success(label)
+
+ def VM_set_security_label(self, session, vm_ref, sec_label, old_label):
+ dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
+ (rc, errors, oldlabel, new_ssidref) = \
+ dom.set_security_label(sec_label, old_label)
+ if rc != xsconstants.XSERR_SUCCESS:
+ return xen_api_error(['SECURITY_ERROR', rc])
+ if rc == 0:
+ rc = new_ssidref
+ return xen_api_success(rc)
+
def VM_create(self, session, vm_struct):
xendom = XendDomain.instance()
domuuid = XendTask.log_progress(0, 100,
@@ -1655,6 +1678,7 @@ class XendAPI(object):
'domid': domid is None and -1 or domid,
'is_control_domain': xeninfo.info['is_control_domain'],
'metrics': xeninfo.get_metrics(),
+ 'security_label': xeninfo.get_security_label(),
'crash_dumps': []
}
return xen_api_success(record)
@@ -1952,7 +1976,8 @@ class XendAPI(object):
'runtime_properties']
VIF_attr_rw = ['device',
'MAC',
- 'MTU']
+ 'MTU',
+ 'security_label']
VIF_attr_inst = VIF_attr_rw
@@ -2054,7 +2079,10 @@ class XendAPI(object):
except Exception, exn:
log.exception(exn)
return xen_api_success({})
-
+
+ def VIF_get_security_label(self, session, vif_ref):
+ return self._VIF_get(vif_ref, 'security_label')
+
# Xen API: Class VIF_metrics
# ----------------------------------------------------------------
@@ -2098,7 +2126,8 @@ class XendAPI(object):
'virtual_size',
'sharable',
'read_only',
- 'other_config']
+ 'other_config',
+ 'security_label']
VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
VDI_methods = [('destroy', None)]
@@ -2206,13 +2235,24 @@ class XendAPI(object):
xennode = XendNode.instance()
return xen_api_success(xennode.get_vdi_by_name_label(name))
+ def VDI_set_security_label(self, session, vdi_ref, sec_lab, old_lab):
+ vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
+ rc = vdi.set_security_label(sec_lab, old_lab)
+ if rc < 0:
+ return xen_api_error(['SECURITY_ERROR', rc])
+ return xen_api_success(rc)
+
+ def VDI_get_security_label(self, session, vdi_ref):
+ vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
+ return xen_api_success(vdi.get_security_label())
# Xen API: Class VTPM
# ----------------------------------------------------------------
VTPM_attr_rw = [ ]
VTPM_attr_ro = ['VM',
- 'backend']
+ 'backend',
+ 'runtime_properties' ]
VTPM_attr_inst = VTPM_attr_rw
@@ -2290,6 +2330,18 @@ class XendAPI(object):
vtpms = reduce(lambda x, y: x + y, vtpms)
return xen_api_success(vtpms)
+ def VTPM_get_runtime_properties(self, _, vtpm_ref):
+ xendom = XendDomain.instance()
+ dominfo = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
+ device = dominfo.get_dev_config_by_uuid('vtpm', vtpm_ref)
+
+ try:
+ device_sxps = dominfo.getDeviceSxprs('vtpm')
+ device_dict = dict(device_sxps[0][1])
+ return xen_api_success(device_dict)
+ except:
+ return xen_api_success({})
+
# Xen API: Class console
# ----------------------------------------------------------------
diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py
index 17628f337a..c84f75df1a 100644
--- a/tools/python/xen/xend/XendConfig.py
+++ b/tools/python/xen/xend/XendConfig.py
@@ -22,6 +22,7 @@ import types
from xen.xend import sxp
from xen.xend import uuid
+from xen.xend import XendOptions
from xen.xend import XendAPIStore
from xen.xend.XendError import VmError
from xen.xend.XendDevices import XendDevices
@@ -29,6 +30,8 @@ from xen.xend.PrettyPrint import prettyprintstring
from xen.xend.XendConstants import DOM_STATE_HALTED
from xen.xend.server.netif import randomMAC
from xen.util.blkif import blkdev_name_to_number
+from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
+from xen.util import xsconstants
log = logging.getLogger("xend.XendConfig")
log.setLevel(logging.WARN)
@@ -159,6 +162,7 @@ XENAPI_CFG_TYPES = {
'platform': dict,
'tools_version': dict,
'other_config': dict,
+ 'security_label': str,
}
# List of legacy configuration keys that have no equivalent in the
@@ -167,7 +171,6 @@ XENAPI_CFG_TYPES = {
LEGACY_UNSUPPORTED_BY_XENAPI_CFG = [
# roundtripped (dynamic, unmodified)
'shadow_memory',
- 'security',
'vcpu_avail',
'cpu_weight',
'cpu_cap',
@@ -318,7 +321,6 @@ class XendConfig(dict):
'memory_static_max': 0,
'memory_dynamic_max': 0,
'devices': {},
- 'security': None,
'on_xend_start': 'ignore',
'on_xend_stop': 'ignore',
'cpus': [],
@@ -392,6 +394,9 @@ class XendConfig(dict):
def _platform_sanity_check(self):
if self.is_hvm():
+ if 'keymap' not in self['platform'] and XendOptions.instance().get_keymap():
+ self['platform']['keymap'] = XendOptions.instance().get_keymap()
+
if 'device_model' not in self['platform']:
self['platform']['device_model'] = DEFAULT_DM
@@ -421,9 +426,10 @@ class XendConfig(dict):
self._memory_sanity_check()
self['cpu_time'] = dominfo['cpu_time']/1e9
- # TODO: i don't know what the security stuff expects here
if dominfo.get('ssidref'):
- self['security'] = [['ssidref', dominfo['ssidref']]]
+ ssidref = int(dominfo.get('ssidref'))
+ self['security_label'] = XSPolicyAdminInstance().ssidref_to_vmlabel(ssidref)
+
self['shutdown_reason'] = dominfo['shutdown_reason']
# parse state into Xen API states
@@ -630,8 +636,26 @@ class XendConfig(dict):
except ValueError, e:
raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e))
- if 'security' in cfg and isinstance(cfg['security'], str):
- cfg['security'] = sxp.from_string(cfg['security'])
+ if 'security' in cfg and not cfg.get('security_label'):
+ secinfo = cfg['security']
+ if isinstance(secinfo, list):
+ # The xm command sends a list formatted like this:
+ # [['access_control', ['policy', 'xm-test'],['label', 'red']],
+ # ['ssidref', 196611]]
+ policy = ""
+ label = ""
+ policytype = xsconstants.ACM_POLICY_ID
+ for idx in range(0, len(secinfo)):
+ if secinfo[idx][0] == "access_control":
+ for aidx in range(1, len(secinfo[idx])):
+ if secinfo[idx][aidx][0] == "policy":
+ policy = secinfo[idx][aidx][1]
+ if secinfo[idx][aidx][0] == "label":
+ label = secinfo[idx][aidx][1]
+ if label != "" and policy != "":
+ cfg['security_label'] = "%s:%s:%s" % \
+ (policytype, policy, label)
+ del cfg['security']
old_state = sxp.child_value(sxp_cfg, 'state')
if old_state:
@@ -774,7 +798,6 @@ class XendConfig(dict):
self[sxp_arg] = val
_set_cfg_if_exists('shadow_memory')
- _set_cfg_if_exists('security')
_set_cfg_if_exists('features')
_set_cfg_if_exists('on_xend_stop')
_set_cfg_if_exists('on_xend_start')
@@ -887,6 +910,9 @@ class XendConfig(dict):
if self.has_key(legacy) and self[legacy] not in (None, []):
sxpr.append([legacy, self[legacy]])
+ if self.has_key('security_label'):
+ sxpr.append(['security_label', self['security_label']])
+
sxpr.append(['image', self.image_sxpr()])
sxpr.append(['status', domain._stateGet()])
diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py
index bca5830185..2f8968f1f8 100644
--- a/tools/python/xen/xend/XendDomain.py
+++ b/tools/python/xen/xend/XendDomain.py
@@ -49,7 +49,7 @@ from xen.xend.XendAPIConstants import *
from xen.xend.xenstore.xstransact import xstransact
from xen.xend.xenstore.xswatch import xswatch
-from xen.util import mkdir, security
+from xen.util import mkdir
from xen.xend import uuid
xc = xen.lowlevel.xc.xc()
@@ -486,7 +486,6 @@ class XendDomain:
"""
self.domains_lock.acquire()
try:
- security.refresh_ssidref(config)
dominfo = XendDomainInfo.restore(config)
return dominfo
finally:
@@ -1113,6 +1112,10 @@ class XendDomain:
raise XendInvalidDomain(str(domid))
if dominfo.getDomid() == DOM0_ID:
raise XendError("Cannot unpause privileged domain %s" % domid)
+ if dominfo._stateGet() not in (DOM_STATE_PAUSED, DOM_STATE_RUNNING):
+ raise VMBadState("Domain '%s' is not started" % domid,
+ POWER_STATE_NAMES[DOM_STATE_PAUSED],
+ POWER_STATE_NAMES[dominfo._stateGet()])
log.info("Domain %s (%d) unpaused.", dominfo.getName(),
int(dominfo.getDomid()))
dominfo.unpause()
@@ -1138,6 +1141,10 @@ class XendDomain:
raise XendInvalidDomain(str(domid))
if dominfo.getDomid() == DOM0_ID:
raise XendError("Cannot pause privileged domain %s" % domid)
+ if dominfo._stateGet() not in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
+ raise VMBadState("Domain '%s' is not started" % domid,
+ POWER_STATE_NAMES[DOM_STATE_RUNNING],
+ POWER_STATE_NAMES[dominfo._stateGet()])
log.info("Domain %s (%d) paused.", dominfo.getName(),
int(dominfo.getDomid()))
dominfo.pause()
@@ -1253,7 +1260,11 @@ class XendDomain:
raise XendInvalidDomain(str(domid))
if dominfo.getDomid() == DOM0_ID:
- raise XendError("Cannot save privileged domain %i" % domid)
+ raise XendError("Cannot save privileged domain %s" % str(domid))
+ if dominfo._stateGet() != DOM_STATE_RUNNING:
+ raise VMBadState("Domain is not running",
+ POWER_STATE_NAMES[DOM_STATE_RUNNING],
+ POWER_STATE_NAMES[dominfo._stateGet()])
oflags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
if hasattr(os, "O_LARGEFILE"):
@@ -1399,10 +1410,15 @@ class XendDomain:
dominfo = self.domain_lookup_nr(domid)
if not dominfo:
raise XendInvalidDomain(str(domid))
- try:
- return xc.sched_credit_domain_get(dominfo.getDomid())
- except Exception, ex:
- raise XendError(str(ex))
+
+ if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
+ try:
+ return xc.sched_credit_domain_get(dominfo.getDomid())
+ except Exception, ex:
+ raise XendError(str(ex))
+ else:
+ return {'weight' : dominfo.getWeight(),
+ 'cap' : dominfo.getCap()}
def domain_sched_credit_set(self, domid, weight = None, cap = None):
"""Set credit scheduler parameters for a domain.
@@ -1436,12 +1452,15 @@ class XendDomain:
assert type(weight) == int
assert type(cap) == int
- rc = xc.sched_credit_domain_set(dominfo.getDomid(), weight, cap)
+ rc = 0
+ if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
+ rc = xc.sched_credit_domain_set(dominfo.getDomid(), weight, cap)
if rc == 0:
if set_weight:
dominfo.setWeight(weight)
if set_cap:
dominfo.setCap(cap)
+ self.managed_config_save(dominfo)
return rc
except Exception, ex:
log.exception(ex)
diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py
index 6860faa9e5..51bd978f3d 100644
--- a/tools/python/xen/xend/XendDomainInfo.py
+++ b/tools/python/xen/xend/XendDomainInfo.py
@@ -489,6 +489,9 @@ class XendDomainInfo:
def send_sysrq(self, key):
""" Send a Sysrq equivalent key via xenstored."""
+ if self._stateGet() not in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
+ raise XendError("Domain '%s' is not started" % self.info['name_label'])
+
asserts.isCharConvertible(key)
self.storeDom("control/sysrq", '%c' % key)
@@ -503,9 +506,18 @@ class XendDomainInfo:
dev_uuid = self.info.device_add(dev_type, cfg_sxp = dev_config)
dev_config_dict = self.info['devices'][dev_uuid][1]
log.debug("XendDomainInfo.device_create: %s" % scrub_password(dev_config_dict))
- dev_config_dict['devid'] = devid = \
- self._createDevice(dev_type, dev_config_dict)
- self._waitForDevice(dev_type, devid)
+
+ if self.domid is not None:
+ try:
+ dev_config_dict['devid'] = devid = \
+ self._createDevice(dev_type, dev_config_dict)
+ self._waitForDevice(dev_type, devid)
+ except VmError, ex:
+ raise ex
+ else:
+ devid = None
+
+ xen.xend.XendDomain.instance().managed_config_save(self)
return self.getDeviceController(dev_type).sxpr(devid)
def device_configure(self, dev_sxp, devid = None):
@@ -819,6 +831,9 @@ class XendDomainInfo:
else:
f('image/%s' % n, v)
+ if self.info.has_key('security_label'):
+ f('security_label', self.info['security_label'])
+
to_store.update(self._vcpuDomDetails())
log.debug("Storing domain details: %s", scrub_password(to_store))
@@ -989,9 +1004,6 @@ class XendDomainInfo:
log.info("Set VCPU count on domain %s to %d", self.info['name_label'],
vcpus)
- def getLabel(self):
- return security.get_security_info(self.info, 'label')
-
def getMemoryTarget(self):
"""Get this domain's target memory size, in KB."""
return self.info['memory_dynamic_max'] / 1024
@@ -1435,11 +1447,20 @@ class XendDomainInfo:
# allocation of 1MB. We free up 2MB here to be on the safe side.
balloon.free(2*1024) # 2MB should be plenty
- self.domid = xc.domain_create(
- domid = 0,
- ssidref = security.get_security_info(self.info, 'ssidref'),
- handle = uuid.fromString(self.info['uuid']),
- hvm = int(hvm))
+ ssidref = security.calc_dom_ssidref_from_info(self.info)
+ if ssidref == 0 and security.on():
+ raise VmError('VM is not properly labeled.')
+
+ try:
+ self.domid = xc.domain_create(
+ domid = 0,
+ ssidref = ssidref,
+ handle = uuid.fromString(self.info['uuid']),
+ hvm = int(hvm))
+ except Exception, e:
+ # may get here if due to ACM the operation is not permitted
+ if security.on():
+ raise VmError('Domain in conflict set with running domain?')
if self.domid < 0:
raise VmError('Creating domain failed: name=%s' %
@@ -1955,24 +1976,6 @@ class XendDomainInfo:
if image_sxpr:
to_store['image'] = sxp.to_string(image_sxpr)
- if self._infoIsSet('security'):
- secinfo = self.info['security']
- to_store['security'] = sxp.to_string(secinfo)
- for idx in range(0, len(secinfo)):
- if secinfo[idx][0] == 'access_control':
- to_store['security/access_control'] = sxp.to_string(
- [secinfo[idx][1], secinfo[idx][2]])
- for aidx in range(1, len(secinfo[idx])):
- if secinfo[idx][aidx][0] == 'label':
- to_store['security/access_control/label'] = \
- secinfo[idx][aidx][1]
- if secinfo[idx][aidx][0] == 'policy':
- to_store['security/access_control/policy'] = \
- secinfo[idx][aidx][1]
- if secinfo[idx][0] == 'ssidref':
- to_store['security/ssidref'] = str(secinfo[idx][1])
-
-
if not self._readVm('xend/restart_count'):
to_store['xend/restart_count'] = str(0)
@@ -2090,15 +2093,6 @@ class XendDomainInfo:
info["maxmem_kb"] = XendNode.instance() \
.physinfo_dict()['total_memory'] * 1024
- #manually update ssidref / security fields
- if security.on() and info.has_key('ssidref'):
- if (info['ssidref'] != 0) and self.info.has_key('security'):
- security_field = self.info['security']
- if not security_field:
- #create new security element
- self.info.update({'security':
- [['ssidref', str(info['ssidref'])]]})
-
#ssidref field not used any longer
if 'ssidref' in info:
info.pop('ssidref')
@@ -2182,7 +2176,133 @@ class XendDomainInfo:
return self.info.get('tools_version', {})
def get_metrics(self):
return self.metrics.get_uuid();
-
+
+
+ def get_security_label(self):
+ domid = self.getDomid()
+
+ from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
+ xspol = XSPolicyAdminInstance().get_loaded_policy()
+
+ if domid == 0:
+ if xspol:
+ label = xspol.policy_get_domain_label_formatted(domid)
+ else:
+ label = ""
+ else:
+ label = self.info.get('security_label', '')
+ return label
+
+ def set_security_label(self, seclab, old_seclab, xspol=None):
+ """
+ Set the security label of a domain from its old to
+ a new value.
+ @param seclab New security label formatted in the form
+ <policy type>:<policy name>:<vm label>
+ @param old_seclab The current security label that the
+ VM must have.
+ @param xspol An optional policy under which this
+ update should be done. If not given,
+ then the current active policy is used.
+ @return Returns return code, a string with errors from
+ the hypervisor's operation, old label of the
+ domain
+ """
+ rc = 0
+ errors = ""
+ old_label = ""
+ new_ssidref = 0
+ domid = self.getDomid()
+ res_labels = None
+
+ from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
+ from xen.util import xsconstants
+
+ state = self._stateGet()
+ # Relabel only HALTED or RUNNING or PAUSED domains
+ if domid != 0 and \
+ state not in \
+ [ DOM_STATE_HALTED, DOM_STATE_RUNNING, DOM_STATE_PAUSED, \
+ DOM_STATE_SUSPENDED ]:
+ log.warn("Relabeling domain not possible in state '%s'" %
+ DOM_STATES[state])
+ return (-xsconstants.XSERR_VM_WRONG_STATE, "", "", 0)
+
+ # Remove security label. Works only for halted domains
+ if not seclab or seclab == "":
+ if state not in [ DOM_STATE_HALTED ]:
+ return (-xsconstants.XSERR_VM_WRONG_STATE, "", "", 0)
+
+ if self.info.has_key('security_label'):
+ old_label = self.info['security_label']
+ # Check label against expected one.
+ if old_label != old_seclab:
+ return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
+ del self.info['security_label']
+ xen.xend.XendDomain.instance().managed_config_save(self)
+ return (xsconstants.XSERR_SUCCESS, "", "", 0)
+
+ tmp = seclab.split(":")
+ if len(tmp) != 3:
+ return (-xsconstants.XSERR_BAD_LABEL_FORMAT, "", "", 0)
+ typ, policy, label = tmp
+
+ poladmin = XSPolicyAdminInstance()
+ if not xspol:
+ xspol = poladmin.get_policy_by_name(policy)
+
+ if state in [ DOM_STATE_RUNNING, DOM_STATE_PAUSED ]:
+ #if domain is running or paused try to relabel in hypervisor
+ if not xspol:
+ return (-xsconstants.XSERR_POLICY_NOT_LOADED, "", "", 0)
+
+ if typ != xspol.get_type_name() or \
+ policy != xspol.get_name():
+ return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
+
+ if typ == xsconstants.ACM_POLICY_ID:
+ new_ssidref = xspol.vmlabel_to_ssidref(label)
+ if new_ssidref == xsconstants.INVALID_SSIDREF:
+ return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
+
+ # Check that all used resources are accessible under the
+ # new label
+ if not security.resources_compatible_with_vmlabel(xspol,
+ self, label):
+ return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
+
+ #Check label against expected one.
+ old_label = self.get_security_label()
+ if old_label != old_seclab:
+ return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
+
+ # relabel domain in the hypervisor
+ rc, errors = security.relabel_domains([[domid, new_ssidref]])
+ log.info("rc from relabeling in HV: %d" % rc)
+ else:
+ return (-xsconstants.XSERR_POLICY_TYPE_UNSUPPORTED, "", "", 0)
+
+ if rc == 0:
+ # HALTED, RUNNING or PAUSED
+ if domid == 0:
+ if xspol:
+ ssidref = poladmin.set_domain0_bootlabel(xspol, label)
+ else:
+ return (-xsconstants.XSERR_POLICY_NOT_LOADED, "", "", 0)
+ else:
+ if self.info.has_key('security_label'):
+ old_label = self.info['security_label']
+ # Check label against expected one, unless wildcard
+ if old_label != old_seclab:
+ return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
+
+ self.info['security_label'] = seclab
+ try:
+ xen.xend.XendDomain.instance().managed_config_save(self)
+ except:
+ pass
+ return (rc, errors, old_label, new_ssidref)
+
def get_on_shutdown(self):
after_shutdown = self.info.get('actions_after_shutdown')
if not after_shutdown or after_shutdown not in XEN_API_ON_NORMAL_EXIT:
diff --git a/tools/python/xen/xend/XendError.py b/tools/python/xen/xend/XendError.py
index 02bab6a2ee..268c3e5d82 100644
--- a/tools/python/xen/xend/XendError.py
+++ b/tools/python/xen/xend/XendError.py
@@ -174,6 +174,23 @@ class NetworkError(XendAPIError):
def __str__(self):
return 'NETWORK_ERROR: %s %s' % (self.error, self.network)
+
+from xen.util.xsconstants import xserr2string
+
+class SecurityError(XendAPIError):
+ def __init__(self, error, message=None):
+ XendAPIError.__init__(self)
+ self.error = error
+ if not message:
+ self.message = xserr2string(-error)
+ else:
+ self.message = message
+
+ def get_api_error(self):
+ return ['SECURITY_ERROR', self.error, self.message]
+
+ def __str__(self):
+ return 'SECURITY_ERROR: %s:%s' % (self.error, self.message)
XEND_ERROR_AUTHENTICATION_FAILED = ('ELUSER', 'Authentication Failed')
XEND_ERROR_SESSION_INVALID = ('EPERMDENIED', 'Session Invalid')
@@ -188,4 +205,5 @@ XEND_ERROR_VIF_INVALID = ('EVIFINVALID', 'VIF Invalid')
XEND_ERROR_VTPM_INVALID = ('EVTPMINVALID', 'VTPM Invalid')
XEND_ERROR_VDI_INVALID = ('EVDIINVALID', 'VDI Invalid')
XEND_ERROR_SR_INVALID = ('ESRINVALID', 'SR Invalid')
+XEND_ERROR_XSPOLICY_INVALID = ('EXSPOLICYINVALID', 'XS Invalid')
XEND_ERROR_TODO = ('ETODO', 'Lazy Programmer Error')
diff --git a/tools/python/xen/xend/XendNode.py b/tools/python/xen/xend/XendNode.py
index b5fa1b7fb4..969c72dbc7 100644
--- a/tools/python/xen/xend/XendNode.py
+++ b/tools/python/xen/xend/XendNode.py
@@ -533,18 +533,70 @@ class XendNode:
['version', ver],
['machine', mch]]
+ def list_to_rangepairs(self,cmap):
+ cmap.sort()
+ pairs = []
+ x = y = 0
+ for i in range(0,len(cmap)):
+ try:
+ if ((cmap[y+1] - cmap[i]) > 1):
+ pairs.append((cmap[x],cmap[y]))
+ x = y = i+1
+ else:
+ y = y + 1
+ # if we go off the end, then just add x to y
+ except IndexError:
+ pairs.append((cmap[x],cmap[y]))
+
+ return pairs
+
+ def format_pairs(self,pairs):
+ if not pairs:
+ return "no cpus"
+ out = ""
+ for f,s in pairs:
+ if (f==s):
+ out += '%d'%f
+ else:
+ out += '%d-%d'%(f,s)
+ out += ','
+ # trim trailing ','
+ return out[:-1]
+
+ def list_to_strrange(self,list):
+ return self.format_pairs(self.list_to_rangepairs(list))
+
+ def format_node_to_cpu(self, pinfo):
+ str=''
+ whitespace=''
+ try:
+ node_to_cpu=pinfo['node_to_cpu']
+ for i in range(0, pinfo['nr_nodes']):
+ str+='%snode%d:%s\n' % (whitespace,
+ i,
+ self.list_to_strrange(node_to_cpu[i]))
+ whitespace='%25s' % ''
+ except:
+ str='none\n'
+ return str[:-1];
+
+ def count_cpus(self, pinfo):
+ count=0
+ node_to_cpu=pinfo['node_to_cpu']
+ for i in range(0, pinfo['nr_nodes']):
+ count+=len(node_to_cpu[i])
+ return count;
+
def physinfo(self):
info = self.xc.physinfo()
- info['nr_cpus'] = (info['nr_nodes'] *
- info['sockets_per_node'] *
- info['cores_per_socket'] *
- info['threads_per_core'])
+ info['nr_cpus'] = self.count_cpus(info)
info['cpu_mhz'] = info['cpu_khz'] / 1000
# physinfo is in KiB, need it in MiB
info['total_memory'] = info['total_memory'] / 1024
info['free_memory'] = info['free_memory'] / 1024
+ info['node_to_cpu'] = self.format_node_to_cpu(info)
ITEM_ORDER = ['nr_cpus',
'nr_nodes',
@@ -555,6 +607,7 @@ class XendNode:
'hw_caps',
'total_memory',
'free_memory',
+ 'node_to_cpu'
]
return [[k, info[k]] for k in ITEM_ORDER]
diff --git a/tools/python/xen/xend/XendOptions.py b/tools/python/xen/xend/XendOptions.py
index 73de5a39c3..af09220782 100644
--- a/tools/python/xen/xend/XendOptions.py
+++ b/tools/python/xen/xend/XendOptions.py
@@ -278,6 +278,9 @@ class XendOptions:
return self.get_config_string('vncpasswd',
self.vncpasswd_default)
+ def get_keymap(self):
+ return self.get_config_value('keymap', None)
+
class XendOptionsFile(XendOptions):
"""Default path to the config file."""
diff --git a/tools/python/xen/xend/XendVDI.py b/tools/python/xen/xend/XendVDI.py
index 140ca01226..10bdee43d3 100644
--- a/tools/python/xen/xend/XendVDI.py
+++ b/tools/python/xen/xend/XendVDI.py
@@ -23,6 +23,7 @@ import os
from xen.util.xmlrpclib2 import stringify
from xmlrpclib import dumps, loads
+from xen.util import security, xsconstants
KB = 1024
MB = 1024 * 1024
@@ -160,6 +161,17 @@ class XendVDI(AutoSaveObject):
def get_location(self):
raise NotImplementedError()
+
+ def set_security_label(self, sec_lab, old_lab):
+ image = self.get_location()
+ rc = security.set_resource_label_xapi(image, sec_lab, old_lab)
+ if rc != xsconstants.XSERR_SUCCESS:
+ raise SecurityError(rc)
+ return rc
+
+ def get_security_label(self):
+ image = self.get_location()
+ return security.get_resource_label_xapi(image)
class XendQCoWVDI(XendVDI):
diff --git a/tools/python/xen/xend/XendXSPolicy.py b/tools/python/xen/xend/XendXSPolicy.py
new file mode 100644
index 0000000000..493b68e199
--- /dev/null
+++ b/tools/python/xen/xend/XendXSPolicy.py
@@ -0,0 +1,222 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#============================================================================
+# Copyright (c) 2007 IBM Corporation
+# Copyright (c) 2006 Xensource
+#============================================================================
+
+import logging
+from xen.xend.XendBase import XendBase
+from xen.xend.XendError import *
+from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
+from xen.util import xsconstants, security
+import base64
+
+log = logging.getLogger("xend.XendXSPolicy")
+log.setLevel(logging.TRACE)
+
+
+class XendXSPolicy(XendBase):
+ """ Administration class for an XSPolicy. """
+
+ def getClass(self):
+ return "XSPolicy"
+
+ def getMethods(self):
+ methods = ['activate_xspolicy']
+ return XendBase.getMethods() + methods
+
+ def getFuncs(self):
+ funcs = [ 'get_xstype',
+ 'set_xspolicy',
+ 'get_xspolicy',
+ 'rm_xsbootpolicy',
+ 'get_resource_label',
+ 'set_resource_label',
+ 'get_labeled_resources' ]
+ return XendBase.getFuncs() + funcs
+
+ getClass = classmethod(getClass)
+ getMethods = classmethod(getMethods)
+ getFuncs = classmethod(getFuncs)
+
+ def __init__(self, xspol, record, uuid):
+ """ xspol = actual XSPolicy object """
+ self.xspol = xspol
+ XendBase.__init__(self, uuid, record)
+
+ def get_record(self):
+ xspol_record = {
+ 'uuid' : self.get_uuid(),
+ 'flags' : XSPolicyAdminInstance().get_policy_flags(self.xspol),
+ 'repr' : self.xspol.toxml(),
+ 'type' : self.xspol.get_type(),
+ }
+ return xspol_record
+
+ def get_xstype(self):
+ return XSPolicyAdminInstance().isXSEnabled()
+
+ def set_xspolicy(self, xstype, xml, flags, overwrite):
+ ref = ""
+ xstype = int(xstype)
+ flags = int(flags)
+
+ polstate = { 'xs_ref': "", 'repr' : "", 'type' : 0,
+ 'flags' : 0 , 'version': 0 , 'errors' : "", 'xserr' : 0 }
+ if xstype == xsconstants.XS_POLICY_ACM:
+ poladmin = XSPolicyAdminInstance()
+ try:
+ (xspol, rc, errors) = poladmin.add_acmpolicy_to_system(
+ xml, flags,
+ overwrite)
+ if rc != 0:
+ polstate.update( { 'xserr' : rc,
+ 'errors': base64.b64encode(errors) } )
+ else:
+ ref = xspol.get_ref()
+ polstate = {
+ 'xs_ref' : ref,
+ 'flags' : poladmin.get_policy_flags(xspol),
+ 'type' : xstype,
+ 'repr' : "",
+ 'version': xspol.get_version(),
+ 'errors' : base64.b64encode(errors),
+ 'xserr' : rc,
+ }
+ except Exception, e:
+ raise
+ else:
+ raise SecurityError(-xsconstants.XSERR_POLICY_TYPE_UNSUPPORTED)
+ return polstate
+
+ def activate_xspolicy(self, flags):
+ flags = int(flags)
+ rc = -xsconstants.XSERR_GENERAL_FAILURE
+ poladmin = XSPolicyAdminInstance()
+ try:
+ rc = poladmin.activate_xspolicy(self.xspol, flags)
+ except Exception, e:
+ log.info("Activate_policy: %s" % str(e))
+ if rc != flags:
+ raise SecurityError(rc)
+ return flags
+
+ def get_xspolicy(self):
+ polstate = { 'xs_ref' : "",
+ 'repr' : "",
+ 'type' : 0,
+ 'flags' : 0,
+ 'version': "",
+ 'errors' : "",
+ 'xserr' : 0 }
+ poladmin = XSPolicyAdminInstance()
+ refs = poladmin.get_policies_refs()
+ # Will return one or no policy
+ if refs and len(refs) > 0:
+ ref = refs[0]
+ xspol = XSPolicyAdminInstance().policy_from_ref(ref)
+ try:
+ xspol.grab_lock()
+
+ polstate = {
+ 'xs_ref' : ref,
+ 'repr' : xspol.toxml(),
+ 'type' : xspol.get_type(),
+ 'flags' : poladmin.get_policy_flags(xspol),
+ 'version': xspol.get_version(),
+ 'errors' : "",
+ 'xserr' : 0,
+ }
+ finally:
+ if xspol:
+ xspol.unlock()
+ return polstate
+
+ def rm_xsbootpolicy(self):
+ rc = XSPolicyAdminInstance().rm_bootpolicy()
+ if rc != xsconstants.XSERR_SUCCESS:
+ raise SecurityError(rc)
+
+ def get_labeled_resources(self):
+ return security.get_labeled_resources_xapi()
+
+ def set_resource_label(self, resource, sec_lab, old_lab):
+ rc = security.set_resource_label_xapi(resource, sec_lab, old_lab)
+ if rc != xsconstants.XSERR_SUCCESS:
+ raise SecurityError(rc)
+
+ def get_resource_label(self, resource):
+ res = security.get_resource_label_xapi(resource)
+ return res
+
+ get_xstype = classmethod(get_xstype)
+ get_xspolicy = classmethod(get_xspolicy)
+ set_xspolicy = classmethod(set_xspolicy)
+ rm_xsbootpolicy = classmethod(rm_xsbootpolicy)
+ set_resource_label = classmethod(set_resource_label)
+ get_resource_label = classmethod(get_resource_label)
+ get_labeled_resources = classmethod(get_labeled_resources)
+
+
+class XendACMPolicy(XendXSPolicy):
+ """ Administration class of an ACMPolicy """
+
+ def getClass(self):
+ return "ACMPolicy"
+
+ def getAttrRO(self):
+ attrRO = [ 'xml',
+ 'map',
+ 'binary',
+ 'header' ]
+ return XendXSPolicy.getAttrRO() + attrRO
+
+ getClass = classmethod(getClass)
+ getAttrRO = classmethod(getAttrRO)
+
+ def __init__(self, acmpol, record, uuid):
+ """ acmpol = actual ACMPolicy object """
+ self.acmpol = acmpol
+ XendXSPolicy.__init__(self, acmpol, record, uuid)
+
+ def get_record(self):
+ polstate = {
+ 'uuid' : self.get_uuid(),
+ 'flags' : XSPolicyAdminInstance().get_policy_flags(self.acmpol),
+ 'repr' : self.acmpol.toxml(),
+ 'type' : self.acmpol.get_type(),
+ }
+ return polstate
+
+ def get_header(self):
+ header = {
+ 'policyname' : "", 'policyurl' : "", 'reference' : "",
+ 'date' : "", 'namespaceurl' : "", 'version' : "",
+ }
+ try:
+ header = self.acmpol.get_header_fields_map()
+ except:
+ pass
+ return header
+
+ def get_xml(self):
+ return self.acmpol.toxml()
+
+ def get_map(self):
+ return self.acmpol.get_map()
+
+ def get_binary(self):
+ polbin = self.acmpol.get_bin()
+ return base64.b64encode(polbin)
diff --git a/tools/python/xen/xend/XendXSPolicyAdmin.py b/tools/python/xen/xend/XendXSPolicyAdmin.py
new file mode 100644
index 0000000000..d3e99c3938
--- /dev/null
+++ b/tools/python/xen/xend/XendXSPolicyAdmin.py
@@ -0,0 +1,314 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#============================================================================
+# Copyright (C) 2006,2007 International Business Machines Corp.
+# Author: Stefan Berger <stefanb@us.ibm.com>
+#============================================================================
+import os
+import shutil
+
+from xml.dom import minidom, Node
+
+from xen.xend.XendLogging import log
+from xen.xend import uuid
+from xen.util import security, xsconstants, dictio, bootloader
+from xen.util.xspolicy import XSPolicy
+from xen.util.acmpolicy import ACMPolicy
+from xen.xend.XendError import SecurityError
+
+XS_MANAGED_POLICIES_FILE = "/etc/xen/acm-security/policies/managed_policies"
+
+class XSPolicyAdmin:
+ """ The class that handles the managed policies in the system.
+ Handles adding and removing managed policies. All managed
+ policies are handled using a reference (UUID) which is
+ assigned to the policy by this class.
+ """
+
+ def __init__(self, maxpolicies):
+ """ Create a management class for managing the system's
+ policies.
+
+ @param maxpolicies: The max. number of policies allowed
+ on the system (currently '1')
+ """
+ self.maxpolicies = maxpolicies
+ try:
+ self.policies = dictio.dict_read("managed_policies",
+ XS_MANAGED_POLICIES_FILE)
+ except Exception, e:
+ self.policies = {}
+
+ self.xsobjs = {}
+ for ref, data in self.policies.items():
+ name = data[0]
+ typ = data[1]
+ try:
+ if typ == xsconstants.ACM_POLICY_ID:
+ self.xsobjs[ref] = ACMPolicy(name=name, ref=ref)
+ else:
+ del self.policies[ref]
+ except Exception, e:
+ log.error("XSPolicyAdmin: Could not find policy '%s': %s" %
+ (name, str(e)))
+ del self.policies[ref]
+ log.debug("XSPolicyAdmin: Known policies: %s" % self.policies)
+
+ def isXSEnabled(self):
+ """ Check whether 'security' is enabled on this system.
+ This currently only checks for ACM-enablement.
+ """
+ rc = 0
+ if security.on():
+ rc |= xsconstants.XS_POLICY_ACM
+ return rc
+
+ def add_acmpolicy_to_system(self, xmltext, flags, overwrite):
+ """ Add an ACM policy's xml representation to the system. The
+ policy will automatically be compiled
+ flags:
+ XS_INST_BOOT : make policy the one to boot the system with
+ by default; if there's a policy already installed,
+ refuse to install this policy unless its one with
+ the same name
+ XS_INST_LOAD : load the policy immediately; if this does not work
+ refuse to install this policy
+ overwrite:
+ If any policy is installed and this is False, refuse to install
+ this policy
+ If flags is True, then any existing policy will be removed from
+ the system and the new one will be installed
+ """
+ errors = ""
+ loadedpol = self.get_loaded_policy()
+ if loadedpol:
+ # This is meant as an update to a currently loaded policy
+ if flags & xsconstants.XS_INST_LOAD == 0:
+ raise SecurityError(-xsconstants.XSERR_POLICY_LOADED)
+ rc, errors = loadedpol.update(xmltext)
+ if rc == 0:
+ self.rm_bootpolicy()
+ irc = self.activate_xspolicy(loadedpol, flags)
+ return (loadedpol, rc, errors)
+
+ try:
+ dom = minidom.parseString(xmltext.encode("utf-8"))
+ except:
+ raise SecurityError(-xsconstants.XSERR_BAD_XML)
+
+ ref = uuid.createString()
+
+ acmpol = ACMPolicy(dom=dom, ref=ref)
+
+ #First some basic tests that do not modify anything:
+
+ if flags & xsconstants.XS_INST_BOOT and not overwrite:
+ filename = acmpol.get_filename(".bin","",dotted=True)
+ if bootloader.get_default_policy != None and \
+ not bootloader.loads_default_policy(filename):
+ raise SecurityError(-xsconstants.XSERR_BOOTPOLICY_INSTALLED)
+
+ if not overwrite and len(self.policies) >= self.maxpolicies:
+ raise SecurityError(-xsconstants.XSERR_BOOTPOLICY_INSTALLED)
+
+ if overwrite:
+ #This should only give one key since only one policy is
+ #allowed.
+ keys = self.policies.keys()
+ for k in keys:
+ self.rm_bootpolicy()
+ rc = self.rm_policy_from_system(k, force=overwrite)
+ if rc != xsconstants.XSERR_SUCCESS:
+ raise SecurityError(rc)
+
+ rc = acmpol.compile()
+ if rc != 0:
+ raise SecurityError(rc)
+
+ if flags & xsconstants.XS_INST_LOAD:
+ rc = acmpol.loadintohv()
+ if rc != 0:
+ raise SecurityError(rc)
+
+ if flags & xsconstants.XS_INST_BOOT:
+ rc = self.make_boot_policy(acmpol)
+ if rc != 0:
+ # If it cannot be installed due to unsupported
+ # bootloader, let it be ok.
+ pass
+
+ if dom:
+ new_entry = { ref : tuple([acmpol.get_name(),
+ xsconstants.ACM_POLICY_ID]) }
+ self.policies.update(new_entry)
+ self.xsobjs[ref] = acmpol
+ dictio.dict_write(self.policies,
+ "managed_policies",
+ XS_MANAGED_POLICIES_FILE)
+ return (acmpol, xsconstants.XSERR_SUCCESS, errors)
+
+ def make_boot_policy(self, acmpol):
+ spolfile = acmpol.get_filename(".bin")
+ dpolfile = "/boot/" + acmpol.get_filename(".bin","",dotted=True)
+ if not os.path.isfile(spolfile):
+ log.error("binary policy file does not exist.")
+ return -xsconstants.XSERR_FILE_ERROR
+ try:
+ shutil.copyfile(spolfile, dpolfile)
+ except:
+ return -xsconstants.XSERR_FILE_ERROR
+
+ try:
+ filename = acmpol.get_filename(".bin","",dotted=True)
+ if bootloader.set_default_boot_policy(filename) != True:
+ return xsconstants.XSERR_BOOTPOLICY_INSTALL_ERROR
+ except:
+ return xsconstants.XSERR_FILE_ERROR
+ return xsconstants.XSERR_SUCCESS
+
+ def activate_xspolicy(self, xspol, flags):
+ rc = xsconstants.XSERR_SUCCESS
+ if flags & xsconstants.XS_INST_LOAD:
+ rc = xspol.loadintohv()
+ if rc == xsconstants.XSERR_SUCCESS and \
+ flags & xsconstants.XS_INST_BOOT:
+ rc = self.make_boot_policy(xspol)
+ if rc == xsconstants.XSERR_SUCCESS:
+ rc = flags
+ return rc
+
+ def rm_policy_from_system(self, ref, force=False):
+ if self.policies.has_key(ref):
+ acmpol = self.xsobjs[ref]
+ rc = acmpol.destroy()
+ if rc == xsconstants.XSERR_SUCCESS or force:
+ del self.policies[ref]
+ del self.xsobjs[ref]
+ dictio.dict_write(self.policies,
+ "managed_policies",
+ XS_MANAGED_POLICIES_FILE)
+ rc = xsconstants.XSERR_SUCCESS
+ return rc
+
+ def rm_bootpolicy(self):
+ """ Remove any (ACM) boot policy from the grub configuration file
+ """
+ rc = 0
+ title = bootloader.get_default_title()
+ if title != None:
+ polnames = []
+ for (k, v) in self.xsobjs.items():
+ polnames.append(v.get_filename(".bin","",dotted=True))
+ bootloader.rm_policy_from_boottitle(title, polnames)
+ else:
+ rc = -xsconstants.XSERR_NO_DEFAULT_BOOT_TITLE
+ return rc
+
+ def get_policy_flags(self, acmpol):
+ """ Get the currently active flags of a policy, i.e., whether the
+ system is using this policy as its boot policy for the default
+ boot title.
+ """
+ flags = 0
+
+ filename = acmpol.get_filename(".bin","", dotted=True)
+ if bootloader.loads_default_policy(filename):
+ flags |= xsconstants.XS_INST_BOOT
+
+ if acmpol.isloaded():
+ flags |= xsconstants.XS_INST_LOAD
+ return flags
+
+ def get_policies(self):
+ """ Get all managed policies. """
+ return self.xsobjs.values()
+
+ def get_policies_refs(self):
+ """ Get all managed policies' references. """
+ return self.xsobjs.keys()
+
+ def has_ref(self, ref):
+ """ Check whether there is a policy with the given reference """
+ return self.xsobjs.has_key(ref)
+
+ def policy_from_ref(self, ref):
+ """ Get the policy's object given its reference """
+ if ref in self.xsobjs.keys():
+ return self.xsobjs[ref]
+ return None
+
+ def ref_from_polname(self, polname):
+ """ Get the reference of the policy given its name """
+ ref = None
+ for (k, v) in self.xsobjs.items():
+ if v.get_name() == polname:
+ ref = k
+ break
+ return ref
+
+ def lock_policy(self, ref):
+ """ get exclusive access to a policy """
+ self.xsobjs[ref].grab_lock()
+
+ def unlock_policy(self, ref):
+ """ release exclusive access to a policy """
+ self.xsobjs[ref].unlock()
+
+ def get_loaded_policy(self):
+ for pol in self.xsobjs.values():
+ if pol.isloaded():
+ return pol
+ return None
+
+ def get_policy_by_name(self, name):
+ for pol in self.xsobjs.values():
+ if pol.get_name() == name:
+ return pol
+ return None
+
+ def get_domain0_bootlabel(self):
+ """ Get the domain0 bootlabel from the default boot title """
+ title = ""
+ def_title = bootloader.get_default_title()
+ line = bootloader.get_kernel_val(def_title, "ssidref")
+ if line:
+ parms = line.split(":",1)
+ if len(parms) > 1:
+ title = parms[1]
+ return title
+
+ def set_domain0_bootlabel(self, xspol, label):
+ """ Set the domain-0 bootlabel under the given policy """
+ return xspol.set_vm_bootlabel(label)
+
+ def rm_domain0_bootlabel(self):
+ """ Remove the domain-0 bootlabel from the default boot title """
+ def_title = bootloader.get_default_title()
+ return bootloader.set_kernel_attval(def_title, "ssidref", None)
+
+ def ssidref_to_vmlabel(self, ssidref):
+ """ Given an ssidref, return the vmlabel under the current policy """
+ vmlabel = ""
+ pol = self.get_loaded_policy()
+ if pol:
+ vmlabel = pol.policy_get_domain_label_by_ssidref_formatted(ssidref)
+ return vmlabel
+
+poladmin = None
+
+def XSPolicyAdminInstance(maxpolicies=1):
+ global poladmin
+ if poladmin == None:
+ poladmin = XSPolicyAdmin(maxpolicies)
+ return poladmin
diff --git a/tools/python/xen/xend/server/SrvDomain.py b/tools/python/xen/xend/server/SrvDomain.py
index 582793b01e..ee9f2d4a7d 100644
--- a/tools/python/xen/xend/server/SrvDomain.py
+++ b/tools/python/xen/xend/server/SrvDomain.py
@@ -155,7 +155,8 @@ class SrvDomain(SrvDir):
def op_domain_sched_credit_set(self, _, req):
fn = FormFn(self.xd.domain_sched_credit_set,
[['dom', 'int'],
- ['weight', 'int']])
+ ['weight', 'int'],
+ ['cap', 'int']])
val = fn(req.args, {'dom': self.dom.domid})
return val
diff --git a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py
index 4623755022..31089b704c 100644
--- a/tools/python/xen/xend/server/blkif.py
+++ b/tools/python/xen/xend/server/blkif.py
@@ -73,10 +73,17 @@ class BlkifController(DevController):
back['uuid'] = uuid
if security.on():
- (label, ssidref, policy) = security.get_res_security_details(uname)
- back.update({'acm_label' : label,
- 'acm_ssidref': str(ssidref),
- 'acm_policy' : policy})
+ (label, ssidref, policy) = \
+ security.get_res_security_details(uname)
+ domain_label = self.vm.get_security_label()
+ if domain_label:
+ rc = security.res_security_check_xapi(label, ssidref, policy,
+ domain_label)
+ if rc == 0:
+ raise VmError("VM's access to block device '%s' denied." %
+ uname)
+ else:
+ raise VmError("VM must have a security label.")
devid = blkif.blkdev_name_to_number(dev)
if devid is None:
diff --git a/tools/python/xen/xend/server/netif.py b/tools/python/xen/xend/server/netif.py
index 3c70b389be..130668428c 100644
--- a/tools/python/xen/xend/server/netif.py
+++ b/tools/python/xen/xend/server/netif.py
@@ -107,6 +107,7 @@ class NetifController(DevController):
uuid = config.get('uuid')
ipaddr = config.get('ip')
model = config.get('model')
+ accel = config.get('accel')
if not typ:
typ = xoptions.netback_type
@@ -131,6 +132,8 @@ class NetifController(DevController):
back['uuid'] = uuid
if model:
back['model'] = model
+ if accel:
+ back['accel'] = accel
config_path = "device/%s/%d/" % (self.deviceClass, devid)
for x in back:
@@ -157,10 +160,10 @@ class NetifController(DevController):
config_path = "device/%s/%d/" % (self.deviceClass, devid)
devinfo = ()
for x in ( 'script', 'ip', 'bridge', 'mac',
- 'type', 'vifname', 'rate', 'uuid', 'model' ):
+ 'type', 'vifname', 'rate', 'uuid', 'model', 'accel'):
y = self.vm._readVm(config_path + x)
devinfo += (y,)
- (script, ip, bridge, mac, typ, vifname, rate, uuid, model) = devinfo
+ (script, ip, bridge, mac, typ, vifname, rate, uuid, model, accel) = devinfo
if script:
result['script'] = script
@@ -180,5 +183,7 @@ class NetifController(DevController):
result['uuid'] = uuid
if model:
result['model'] = model
+ if accel:
+ result['accel'] = accel
return result
diff --git a/tools/python/xen/xend/server/vfbif.py b/tools/python/xen/xend/server/vfbif.py
index cbef190248..eb1990e64f 100644
--- a/tools/python/xen/xend/server/vfbif.py
+++ b/tools/python/xen/xend/server/vfbif.py
@@ -76,6 +76,11 @@ class VfbifController(DevController):
args += [ "--listen", vnclisten ]
if config.has_key("keymap"):
args += ["-k", "%s" % config["keymap"]]
+ else:
+ xoptions = xen.xend.XendOptions.instance()
+ if xoptions.get_keymap():
+ args += ["-k", "%s" % xoptions.get_keymap()]
+
spawn_detached(args[0], args + std_args, os.environ)
elif t == "sdl":
args = [xen.util.auxbin.pathTo("xen-sdlfb")]
diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py
index 79fa947bb6..42dc8f32fd 100644
--- a/tools/python/xen/xm/create.py
+++ b/tools/python/xen/xm/create.py
@@ -318,7 +318,8 @@ gopts.var('vfb', val="type={vnc,sdl},vncunused=1,vncdisplay=N,vnclisten=ADDR,dis
given DISPLAY and XAUTHORITY, which default to the current user's
ones.""")
-gopts.var('vif', val="type=TYPE,mac=MAC,bridge=BRIDGE,ip=IPADDR,script=SCRIPT,backend=DOM,vifname=NAME",
+gopts.var('vif', val="type=TYPE,mac=MAC,bridge=BRIDGE,ip=IPADDR,script=SCRIPT," + \
+ "backend=DOM,vifname=NAME,rate=RATE,model=MODEL,accel=ACCEL",
fn=append_value, default=[],
use="""Add a network interface with the given MAC address and bridge.
The vif is configured by calling the given configuration script.
@@ -330,6 +331,9 @@ gopts.var('vif', val="type=TYPE,mac=MAC,bridge=BRIDGE,ip=IPADDR,script=SCRIPT,ba
If backend is not specified the default backend driver domain is used.
If vifname is not specified the backend virtual interface will have name vifD.N
where D is the domain id and N is the interface id.
+ If rate is not specified the default rate is used.
+ If model is not specified the default model is used.
+ If accel is not specified an accelerator plugin module is not used.
This option may be repeated to add more than one vif.
Specifying vifs will increase the number of interfaces as needed.""")
@@ -710,7 +714,7 @@ def configure_vifs(config_devs, vals):
def f(k):
if k not in ['backend', 'bridge', 'ip', 'mac', 'script', 'type',
- 'vifname', 'rate', 'model']:
+ 'vifname', 'rate', 'model', 'accel']:
err('Invalid vif option: ' + k)
config_vif.append([k, d[k]])
diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py
index 8bc0efe90a..646f796633 100644
--- a/tools/python/xen/xm/main.py
+++ b/tools/python/xen/xm/main.py
@@ -700,13 +700,7 @@ def xm_save(args):
if serverType == SERVER_XEN_API:
server.xenapi.VM.save(get_single_vm(dom), savefile, checkpoint)
else:
- try:
- dominfo = parse_doms_info(server.xend.domain(dom))
- except xmlrpclib.Fault, ex:
- raise ex
-
- domid = dominfo['domid']
- server.xend.domain.save(domid, savefile, checkpoint)
+ server.xend.domain.save(dom, savefile, checkpoint)
def xm_restore(args):
arg_check(args, "restore", 1, 2)
@@ -1529,7 +1523,7 @@ def xm_sched_credit(args):
doms = filter(lambda x : domid_match(domid, x),
[parse_doms_info(dom)
- for dom in getDomains(None, 'running')])
+ for dom in getDomains(None, 'all')])
if weight is None and cap is None:
if domid is not None and doms == []:
@@ -1545,7 +1539,7 @@ def xm_sched_credit(args):
server.xenapi.VM.get_metrics(
get_single_vm(d['name'])))
else:
- info = server.xend.domain.sched_credit_get(d['domid'])
+ info = server.xend.domain.sched_credit_get(d['name'])
except xmlrpclib.Fault:
pass
@@ -1557,8 +1551,8 @@ def xm_sched_credit(args):
info['cap'] = int(info['cap'])
info['name'] = d['name']
- info['domid'] = int(d['domid'])
- print( ("%(name)-32s %(domid)5d %(weight)6d %(cap)4d") % info)
+ info['domid'] = str(d['domid'])
+ print( ("%(name)-32s %(domid)5s %(weight)6d %(cap)4d") % info)
else:
if domid is None:
# place holder for system-wide scheduler parameters
@@ -1566,14 +1560,24 @@ def xm_sched_credit(args):
usage('sched-credit')
if serverType == SERVER_XEN_API:
- server.xenapi.VM.add_to_VCPUs_params_live(
- get_single_vm(domid),
- "weight",
- weight)
- server.xenapi.VM.add_to_VCPUs_params_live(
- get_single_vm(domid),
- "cap",
- cap)
+ if doms[0]['domid']:
+ server.xenapi.VM.add_to_VCPUs_params_live(
+ get_single_vm(domid),
+ "weight",
+ weight)
+ server.xenapi.VM.add_to_VCPUs_params_live(
+ get_single_vm(domid),
+ "cap",
+ cap)
+ else:
+ server.xenapi.VM.add_to_VCPUs_params(
+ get_single_vm(domid),
+ "weight",
+ weight)
+ server.xenapi.VM.add_to_VCPUs_params(
+ get_single_vm(domid),
+ "cap",
+ cap)
else:
result = server.xend.domain.sched_credit_set(domid, weight, cap)
if result != 0:
diff --git a/tools/security/policies/security_policy.xsd b/tools/security/policies/security_policy.xsd
index 8789adb9de..f797cdda77 100644
--- a/tools/security/policies/security_policy.xsd
+++ b/tools/security/policies/security_policy.xsd
@@ -22,7 +22,7 @@
<xsd:element name="Reference" type="xsd:string" minOccurs="0" maxOccurs="1" />
<xsd:element name="Date" minOccurs="0" maxOccurs="1" type="xsd:string"></xsd:element>
<xsd:element name="NameSpaceUrl" minOccurs="0" maxOccurs="1" type="xsd:string"></xsd:element>
- <xsd:element name="Version" minOccurs="0" maxOccurs="1" type="VersionFormat"/>
+ <xsd:element name="Version" minOccurs="1" maxOccurs="1" type="VersionFormat"/>
<xsd:element ref="FromPolicy" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
@@ -91,23 +91,23 @@
<xsd:sequence>
<xsd:element maxOccurs="unbounded" minOccurs="1" ref="Type" />
</xsd:sequence>
- <xsd:attribute name="name" type="xsd:string" use="optional"></xsd:attribute>
+ <xsd:attribute name="name" type="xsd:string" use="required"></xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="VirtualMachineLabel">
<xsd:complexType>
<xsd:sequence>
- <xsd:element ref="Name"></xsd:element>
+ <xsd:element name="Name" type="NameWithFrom"></xsd:element>
<xsd:element ref="SimpleTypeEnforcementTypes" minOccurs="0" maxOccurs="unbounded" />
- <xsd:element ref="ChineseWallTypes" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element name="ChineseWallTypes" type="SingleChineseWallType" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="ResourceLabel">
<xsd:complexType>
<xsd:sequence>
- <xsd:element ref="Name"></xsd:element>
- <xsd:element ref="SimpleTypeEnforcementTypes" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element name="Name" type="NameWithFrom"></xsd:element>
+ <xsd:element name="SimpleTypeEnforcementTypes" type="SingleSimpleTypeEnforcementType" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
@@ -131,4 +131,21 @@
<xsd:pattern value="[0-9]{1,8}.[0-9]{1,8}"></xsd:pattern>
</xsd:restriction>
</xsd:simpleType>
+ <xsd:complexType name="NameWithFrom">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="from" type="xsd:string" use="optional"></xsd:attribute>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="SingleSimpleTypeEnforcementType">
+ <xsd:sequence>
+ <xsd:element maxOccurs="1" minOccurs="1" ref="Type" />
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="SingleChineseWallType">
+ <xsd:sequence>
+ <xsd:element maxOccurs="1" minOccurs="1" ref="Type" />
+ </xsd:sequence>
+ </xsd:complexType>
</xsd:schema>
diff --git a/tools/security/xensec_ezpolicy b/tools/security/xensec_ezpolicy
index 970fb380b4..458ff556f2 100644
--- a/tools/security/xensec_ezpolicy
+++ b/tools/security/xensec_ezpolicy
@@ -1102,8 +1102,10 @@ def org2dict():
for i in iterchildren(app.win.orgs.GetRootItem()):
d = []
for j in iterchildren(i):
- d.append(str(app.win.orgspanel.orgs.GetItemText(j)))
- o.append([str(app.win.orgspanel.orgs.GetItemText(i)) , d])
+ d.append(
+ str(app.win.orgspanel.orgs.GetItemText(j).encode("utf-8")))
+ o.append([str(app.win.orgspanel.orgs.GetItemText(i).encode("utf-8")),
+ d])
dic['orgs'] = o
c=[]
for i in app.win.conspanel.conflictsets:
@@ -1175,12 +1177,14 @@ def printPolicy(fd, types, cons):
continue
#name is optional but must be set
if i[0]:
- rer_name = str(i[0])
+ rer_name = i[0]
else:
- rer_name = str("RER")
- fd.write(""" <Conflict name=\"%s\">\n""" % rer_name)
+ rer_name = "RER"
+ fd.write(""" <Conflict name=\"""" +
+ rer_name.encode("utf-8") + """\">\n""")
for j in i[1]:
- fd.write(""" <Type>%s</Type>\n""" % str(j))
+ typ = j.encode("utf-8")
+ fd.write(""" <Type>%s</Type>\n""" % typ)
fd.write(""" </Conflict>\n""")
fd.write(""" </ConflictSets>\n""")
diff --git a/tools/xcutils/Makefile b/tools/xcutils/Makefile
index f8ac92f7d9..df7ee8613f 100644
--- a/tools/xcutils/Makefile
+++ b/tools/xcutils/Makefile
@@ -15,7 +15,7 @@ PROGRAMS_INSTALL_DIR = /usr/$(LIBDIR)/xen/bin
INCLUDES += -I $(XEN_LIBXC) -I $(XEN_XENSTORE)
-CFLAGS += -Werror -fno-strict-aliasing
+CFLAGS += -Werror
CFLAGS += $(INCLUDES)
# Make gcc generate dependencies.
diff --git a/tools/xenmon/xenbaked.c b/tools/xenmon/xenbaked.c
index 5908a6c1c9..1587016335 100644
--- a/tools/xenmon/xenbaked.c
+++ b/tools/xenmon/xenbaked.c
@@ -444,7 +444,7 @@ struct t_rec **init_rec_ptrs(struct t_buf **meta, unsigned int num)
*/
unsigned int get_num_cpus(void)
{
- xc_physinfo_t physinfo;
+ xc_physinfo_t physinfo = { 0 };
int xc_handle = xc_interface_open();
int ret;
diff --git a/tools/xenstat/libxenstat/src/xenstat.c b/tools/xenstat/libxenstat/src/xenstat.c
index 93d228c2f6..a109960c41 100644
--- a/tools/xenstat/libxenstat/src/xenstat.c
+++ b/tools/xenstat/libxenstat/src/xenstat.c
@@ -135,7 +135,7 @@ xenstat_node *xenstat_get_node(xenstat_handle * handle, unsigned int flags)
{
#define DOMAIN_CHUNK_SIZE 256
xenstat_node *node;
- xc_physinfo_t physinfo;
+ xc_physinfo_t physinfo = { 0 };
xc_domaininfo_t domaininfo[DOMAIN_CHUNK_SIZE];
unsigned int new_domains;
unsigned int i;
diff --git a/tools/xenstore/Makefile b/tools/xenstore/Makefile
index 92268ca875..a754fab85f 100644
--- a/tools/xenstore/Makefile
+++ b/tools/xenstore/Makefile
@@ -11,15 +11,11 @@ BASECFLAGS=-Werror
BASECFLAGS += -Wp,-MD,.$(@F).d
PROG_DEP = .*.d
BASECFLAGS+= $(PROFILE)
-#BASECFLAGS+= -I$(XEN_ROOT)/tools
BASECFLAGS+= -I$(XEN_ROOT)/tools/libxc
BASECFLAGS+= -I.
CFLAGS += $(BASECFLAGS)
LDFLAGS += $(PROFILE) -L$(XEN_LIBXC)
-TESTDIR = testsuite/tmp
-TESTFLAGS= -DTESTING
-TESTENV = XENSTORED_ROOTDIR=$(TESTDIR) XENSTORED_RUNDIR=$(TESTDIR)
CLIENTS := xenstore-exists xenstore-list xenstore-read xenstore-rm xenstore-chmod
CLIENTS += xenstore-write
@@ -35,12 +31,6 @@ XENSTORED_OBJS += $(XENSTORED_OBJS_y)
.PHONY: all
all: libxenstore.so libxenstore.a xenstored $(CLIENTS) xs_tdb_dump xenstore-control xenstore-ls
-test_interleaved_transactions: test_interleaved_transactions.o
- $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o $@
-
-.PHONY: testcode
-testcode: xs_test xenstored_test xs_random
-
xenstored: $(XENSTORED_OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl $(SOCKET_LIBS) -o $@
@@ -56,35 +46,9 @@ xenstore-control: xenstore_control.o libxenstore.so
xenstore-ls: xsls.o libxenstore.so
$(CC) $(CFLAGS) $(LDFLAGS) $< $(LOADLIBES) $(LDLIBS) -L. -lxenstore $(SOCKET_LIBS) -o $@
-xenstored_test: xenstored_core_test.o xenstored_watch_test.o xenstored_domain_test.o xenstored_transaction_test.o xs_lib.o talloc_test.o fake_libxc.o utils.o tdb.o
- $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
-
xs_tdb_dump: xs_tdb_dump.o utils.o tdb.o talloc.o
$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
-xs_test xs_random xs_stress xs_crashme: LDFLAGS+=-lpthread
-xs_test: xs_test.o xs_lib.o utils.o
-xs_random: xs_random.o xs_test_lib.o xs_lib.o talloc.o utils.o
-xs_stress: xs_stress.o xs_test_lib.o xs_lib.o talloc.o utils.o
-xs_crashme: xs_crashme.o xs_lib.o talloc.o utils.o
-
-speedtest: speedtest.o xs.o xs_lib.o utils.o talloc.o
-
-.PHONY: check-speed
-check-speed: speedtest xenstored_test $(TESTDIR)
- $(TESTENV) time ./speedtest 100
-
-xs_test.o xs_stress.o xenstored_core_test.o xenstored_watch_test.o xenstored_transaction_test.o xenstored_domain_test.o xs_random.o xs_test_lib.o talloc_test.o fake_libxc.o xs_crashme.o: CFLAGS=$(BASECFLAGS) $(TESTFLAGS)
-
-xenstored_%_test.o: xenstored_%.c
- $(COMPILE.c) -o $@ $<
-
-xs_test_lib.o: xs.c
- $(COMPILE.c) -o $@ $<
-
-talloc_test.o: talloc.c
- $(COMPILE.c) -o $@ $<
-
libxenstore.so: libxenstore.so.$(MAJOR)
ln -sf $< $@
libxenstore.so.$(MAJOR): libxenstore.so.$(MAJOR).$(MINOR)
@@ -97,67 +61,13 @@ libxenstore.a: xs.o xs_lib.o
$(AR) rcs libxenstore.a $^
.PHONY: clean
-clean: testsuite-clean
+clean:
rm -f *.a *.o *.opic *.so*
rm -f xenstored xs_random xs_stress xs_crashme
- rm -f xs_test xenstored_test xs_tdb_dump xenstore-control xenstore-ls
+ rm -f xs_tdb_dump xenstore-control xenstore-ls
rm -f $(CLIENTS)
$(RM) $(PROG_DEP)
-.PHONY: print-dir
-print-dir:
- @echo -n tools/xenstore:
-
-.PHONY: print-end
-print-end:
- @echo
-
-.PHONY: check
-check: print-dir testsuite-fast randomcheck-fast print-end
-
-.PHONY: fullcheck
-fullcheck: testsuite-run randomcheck stresstest
-
-$(TESTDIR):
- mkdir $@
-
-.PHONY: testsuite-run
-testsuite-run: xenstored_test xs_test $(TESTDIR)
- $(TESTENV) testsuite/test.sh && echo
-
-.PHONY: testsuite-fast
-testsuite-fast: xenstored_test xs_test $(TESTDIR)
- @$(TESTENV) testsuite/test.sh --fast
-
-.PHONY: testsuite-clean
-testsuite-clean:
- rm -rf $(TESTDIR)
-
-# Make this visible so they can see repeat tests without --fast if they
-# fail.
-RANDSEED=$(shell date +%s)
-.PHONY: randomcheck
-randomcheck: xs_random xenstored_test $(TESTDIR)
- $(TESTENV) ./xs_random --simple --fast /tmp/xs_random 200000 $(RANDSEED) && echo
- $(TESTENV) ./xs_random --fast /tmp/xs_random 100000 $(RANDSEED) && echo
-# $(TESTENV) ./xs_random --fail /tmp/xs_random 10000 $(RANDSEED)
-
-.PHONY: crashme
-crashme: xs_crashme xenstored_test $(TESTDIR)
- rm -rf $(TESTDIR)/store $(TESTDIR)/transactions /tmp/xs_crashme.vglog* /tmp/trace
- export $(TESTENV); ./xs_crashme 5000 $(RANDSEED) 2>/dev/null
- if [ -n "`cat /tmp/xs_crashme.vglog*`" ]; then echo Valgrind complained; cat /tmp/xs_crashme.vglog*; exit 1; fi
- rm -rf $(TESTDIR)/store $(TESTDIR)/transactions /tmp/xs_crashme.vglog* /tmp/trace
-
-.PHONY: randomcheck-fast
-randomcheck-fast: xs_random xenstored_test $(TESTDIR)
- @$(TESTENV) ./xs_random --fast /tmp/xs_random 2000 $(RANDSEED)
-
-.PHONY: stresstest
-stresstest: xs_stress xenstored_test $(TESTDIR)
- rm -rf $(TESTDIR)/store $(TESTDIR)/transactions
- export $(TESTENV); PID=`./xenstored_test --output-pid --trace-file=/tmp/trace`; ./xs_stress 5000; ret=$$?; kill $$PID; exit $$ret
-
.PHONY: TAGS
TAGS:
etags `find . -name '*.[ch]'`
diff --git a/tools/xenstore/fake_libxc.c b/tools/xenstore/fake_libxc.c
deleted file mode 100644
index 77c2095a4e..0000000000
--- a/tools/xenstore/fake_libxc.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- Fake libxc which doesn't require hypervisor but talks to xs_test.
- Copyright (C) 2005 Rusty Russell IBM Corporation
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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 <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <unistd.h>
-#include <assert.h>
-#include <signal.h>
-#include "utils.h"
-#include "xenstored_core.h"
-#include "xenstored_domain.h"
-#include "xenstored_test.h"
-#include <xenctrl.h>
-
-static int sigfd;
-static int xs_test_pid;
-static evtchn_port_t port;
-
-/* The event channel maps to a signal, shared page to an mmapped file. */
-void xc_evtchn_notify(int xce_handle, int local_port)
-{
- assert(local_port == port);
- if (kill(xs_test_pid, SIGUSR2) != 0)
- barf_perror("fake event channel failed");
-}
-
-void *xc_map_foreign_range(int xc_handle, uint32_t dom __attribute__((unused)),
- int size, int prot,
- unsigned long mfn __attribute__((unused)))
-{
- void *ret;
-
- ret = mmap(NULL, size, prot, MAP_SHARED, xc_handle, 0);
- if (ret == MAP_FAILED)
- return NULL;
-
- /* xs_test tells us pid and port by putting it in buffer, we reply. */
- xs_test_pid = *(int *)(ret + 32);
- port = *(int *)(ret + 36);
- *(int *)(ret + 32) = getpid();
- return ret;
-}
-
-int xc_interface_open(void)
-{
- int fd;
- char page[getpagesize()];
-
- fd = open("/tmp/xcmap", O_RDWR|O_CREAT|O_TRUNC, 0600);
- if (fd < 0)
- return fd;
-
- memset(page, 0, sizeof(page));
- if (!xs_write_all(fd, page, sizeof(page)))
- barf_perror("Failed to write /tmp/xcmap page");
-
- return fd;
-}
-
-int xc_interface_close(int xc_handle)
-{
- close(xc_handle);
- return 0;
-}
-
-int xc_domain_getinfo(int xc_handle __attribute__((unused)),
- uint32_t first_domid, unsigned int max_doms,
- xc_dominfo_t *info)
-{
- assert(max_doms == 1);
- info->domid = first_domid;
-
- info->dying = 0;
- info->shutdown = 0;
- info->paused = 0;
- info->blocked = 0;
- info->running = 1;
-
- info->shutdown_reason = 0;
-
- if ( info->shutdown && (info->shutdown_reason == SHUTDOWN_crash) )
- {
- info->shutdown = 0;
- info->crashed = 1;
- }
-
- return 1;
-}
-
-static void send_to_fd(int signo __attribute__((unused)))
-{
- int saved_errno = errno;
- write(sigfd, &port, sizeof(port));
- errno = saved_errno;
-}
-
-void fake_block_events(void)
-{
- signal(SIGUSR2, SIG_IGN);
-}
-
-void fake_ack_event(void)
-{
- signal(SIGUSR2, send_to_fd);
-}
-
-int xc_evtchn_open(void)
-{
- int fds[2];
-
- if (pipe(fds) != 0)
- return -1;
-
- if (signal(SIGUSR2, send_to_fd) == SIG_ERR) {
- int saved_errno = errno;
- close(fds[0]);
- close(fds[1]);
- errno = saved_errno;
- return -1;
- }
- sigfd = fds[1];
- return fds[0];
-}
diff --git a/tools/xenstore/speedtest.c b/tools/xenstore/speedtest.c
deleted file mode 100644
index 632e926f56..0000000000
--- a/tools/xenstore/speedtest.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- Xen Store Daemon Speed test
- Copyright (C) 2005 Rusty Russell IBM Corporation
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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 <stdlib.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include "utils.h"
-#include "xs.h"
-#include "list.h"
-#include "talloc.h"
-
-static void do_command(const char *cmd)
-{
- int ret;
-
- ret = system(cmd);
- if (ret == -1 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0)
- barf_perror("Failed '%s': %i", cmd, ret);
-}
-
-static int start_daemon(void)
-{
- int fds[2], pid;
-
- do_command(talloc_asprintf(NULL, "rm -rf testsuite/tmp/*"));
-
- /* Start daemon. */
- pipe(fds);
- if ((pid = fork())) {
- /* Child writes PID when its ready: we wait for that. */
- char buffer[20];
- close(fds[1]);
- if (read(fds[0], buffer, sizeof(buffer)) < 0)
- barf("Failed to summon daemon");
- close(fds[0]);
- } else {
- dup2(fds[1], STDOUT_FILENO);
- close(fds[0]);
-#if 0
- execlp("valgrind", "valgrind", "-q", "--suppressions=testsuite/vg-suppressions", "xenstored_test", "--output-pid",
- "--no-fork", "--trace-file=/tmp/trace", NULL);
-#else
- execlp("./xenstored_test", "xenstored_test", "--output-pid", "--no-fork", NULL);
-// execlp("strace", "strace", "-o", "/tmp/out", "./xenstored_test", "--output-pid", "--no-fork", NULL);
-#endif
- exit(1);
- }
- return pid;
-}
-
-static void kill_daemon(int pid)
-{
- int saved_errno = errno;
- kill(pid, SIGTERM);
- errno = saved_errno;
-}
-
-#define NUM_ENTRIES 50
-
-/* We create the given number of trees, each with NUM_ENTRIES, using
- * transactions. */
-int main(int argc, char *argv[])
-{
- int i, j, pid, print;
- struct xs_handle *h;
-
- if (argc != 2)
- barf("Usage: speedtest <numdomains>");
-
- pid = start_daemon();
- h = xs_daemon_open();
- print = atoi(argv[1]) / 76;
- if (!print)
- print = 1;
- for (i = 0; i < atoi(argv[1]); i ++) {
- char name[64];
-
- if (i % print == 0)
- write(1, ".", 1);
- if (!xs_transaction_start(h)) {
- kill_daemon(pid);
- barf_perror("Starting transaction");
- }
- sprintf(name, "/%i", i);
- if (!xs_mkdir(h, name)) {
- kill_daemon(pid);
- barf_perror("Making directory %s", name);
- }
-
- for (j = 0; j < NUM_ENTRIES; j++) {
- sprintf(name, "/%i/%i", i, j);
- if (!xs_write(h, name, name, strlen(name))) {
- kill_daemon(pid);
- barf_perror("Making directory %s", name);
- }
- }
- if (!xs_transaction_end(h, false)) {
- kill_daemon(pid);
- barf_perror("Ending transaction");
- }
- }
- write(1, "\n", 1);
-
- kill_daemon(pid);
- wait(NULL);
- return 0;
-}
-
-
diff --git a/tools/xenstore/testsuite/01simple.test b/tools/xenstore/testsuite/01simple.test
deleted file mode 100644
index 8f3459522a..0000000000
--- a/tools/xenstore/testsuite/01simple.test
+++ /dev/null
@@ -1,4 +0,0 @@
-# Create an entry, read it.
-write /test contents
-expect contents
-read /test
diff --git a/tools/xenstore/testsuite/02directory.test b/tools/xenstore/testsuite/02directory.test
deleted file mode 100644
index 1f57f9360e..0000000000
--- a/tools/xenstore/testsuite/02directory.test
+++ /dev/null
@@ -1,45 +0,0 @@
-# Root directory has only tool dir in it.
-expect tool
-dir /
-
-# Create a file.
-write /test contents
-
-# Directory shows it.
-expect test
-expect tool
-dir /
-
-# Make a new directory, check it's there
-mkdir /dir
-expect dir
-expect test
-expect tool
-dir /
-
-# Check it's empty.
-dir /dir
-
-# Create a file, check it exists.
-write /dir/test2 contents2
-expect test2
-dir /dir
-expect contents2
-read /dir/test2
-
-# Creating dir over the top should succeed.
-mkdir /dir
-mkdir /dir/test2
-
-# Mkdir implicitly creates directories.
-mkdir /dir/1/2/3/4
-expect test2
-expect 1
-dir /dir
-expect 2
-dir /dir/1
-expect 3
-dir /dir/1/2
-expect 4
-dir /dir/1/2/3
-dir /dir/1/2/3/4
diff --git a/tools/xenstore/testsuite/03write.test b/tools/xenstore/testsuite/03write.test
deleted file mode 100644
index 4ce4ad4374..0000000000
--- a/tools/xenstore/testsuite/03write.test
+++ /dev/null
@@ -1,28 +0,0 @@
-# Write succeeds
-write /test contents
-expect contents
-read /test
-
-# Overwrite succeeds.
-write /test contents2
-expect contents2
-read /test
-
-# Write should implicitly create directories
-write /dir/test contents
-expect test
-dir /dir
-expect contents
-read /dir/test
-write /dir/1/2/3/4 contents4
-expect test
-expect 1
-dir /dir
-expect 2
-dir /dir/1
-expect 3
-dir /dir/1/2
-expect 4
-dir /dir/1/2/3
-expect contents4
-read /dir/1/2/3/4
diff --git a/tools/xenstore/testsuite/04rm.test b/tools/xenstore/testsuite/04rm.test
deleted file mode 100644
index ae49fd045b..0000000000
--- a/tools/xenstore/testsuite/04rm.test
+++ /dev/null
@@ -1,20 +0,0 @@
-# Remove non-existant is OK, as long as parent exists
-rm /test
-expect rm failed: No such file or directory
-rm /dir/test
-
-# Create file and remove it
-write /test contents
-rm /test
-expect tool
-dir /
-
-# Create directory and remove it.
-mkdir /dir
-rm /dir
-
-# Create directory, create file, remove all.
-mkdir /dir
-write /dir/test contents
-rm /dir
-
diff --git a/tools/xenstore/testsuite/05filepermissions.test b/tools/xenstore/testsuite/05filepermissions.test
deleted file mode 100644
index 33089a6e7f..0000000000
--- a/tools/xenstore/testsuite/05filepermissions.test
+++ /dev/null
@@ -1,81 +0,0 @@
-# Fail to get perms on non-existent file.
-expect getperm failed: No such file or directory
-getperm /test
-expect getperm failed: No such file or directory
-getperm /dir/test
-
-# Create file: inherits from root (0 READ)
-write /test contents
-expect 0 READ
-getperm /test
-setid 1
-expect 0 READ
-getperm /test
-expect contents
-read /test
-expect write failed: Permission denied
-write /test contents
-
-# Take away read access to file.
-setid 0
-setperm /test 0 NONE
-setid 1
-expect getperm failed: Permission denied
-getperm /test
-expect read failed: Permission denied
-read /test
-expect write failed: Permission denied
-write /test contents
-
-# Grant everyone write access to file.
-setid 0
-setperm /test 0 WRITE
-setid 1
-expect getperm failed: Permission denied
-getperm /test
-expect read failed: Permission denied
-read /test
-write /test contents2
-setid 0
-expect contents2
-read /test
-
-# Grant everyone both read and write access.
-setperm /test 0 READ/WRITE
-setid 1
-expect 0 READ/WRITE
-getperm /test
-expect contents2
-read /test
-write /test contents3
-expect contents3
-read /test
-
-# Change so that user 1 owns it, noone else can do anything.
-setid 0
-setperm /test 1 NONE
-setid 1
-expect 1 NONE
-getperm /test
-expect contents3
-read /test
-write /test contents4
-
-# User 2 can do nothing.
-setid 2
-expect setperm failed: Permission denied
-setperm /test 2 NONE
-expect getperm failed: Permission denied
-getperm /test
-expect read failed: Permission denied
-read /test
-expect write failed: Permission denied
-write /test contents4
-
-# Tools can always access things.
-setid 0
-expect 1 NONE
-getperm /test
-expect contents4
-read /test
-write /test contents5
diff --git a/tools/xenstore/testsuite/06dirpermissions.test b/tools/xenstore/testsuite/06dirpermissions.test
deleted file mode 100644
index 2e828a8d0f..0000000000
--- a/tools/xenstore/testsuite/06dirpermissions.test
+++ /dev/null
@@ -1,119 +0,0 @@
-# Root directory: owned by tool, everyone has read access.
-expect 0 READ
-getperm /
-
-# Create directory: inherits from root.
-mkdir /dir
-expect 0 READ
-getperm /dir
-setid 1
-expect 0 READ
-getperm /dir
-dir /dir
-expect write failed: Permission denied
-write /dir/test contents2
-
-# Remove everyone's read access to directoy.
-setid 0
-setperm /dir 0 NONE
-setid 1
-expect dir failed: Permission denied
-dir /dir
-expect read failed: Permission denied
-read /dir/test create contents2
-expect write failed: Permission denied
-write /dir/test contents2
-
-# Grant everyone write access to directory.
-setid 0
-setperm /dir 0 WRITE
-setid 1
-expect getperm failed: Permission denied
-getperm /dir
-expect dir failed: Permission denied
-dir /dir
-write /dir/test contents
-setid 0
-expect 1 WRITE
-getperm /dir/test
-setperm /dir/test 0 NONE
-expect contents
-read /dir/test
-
-# Grant everyone both read and write access.
-setperm /dir 0 READ/WRITE
-setid 1
-expect 0 READ/WRITE
-getperm /dir
-expect test
-dir /dir
-write /dir/test2 contents
-expect contents
-read /dir/test2
-setperm /dir/test2 1 NONE
-
-# Change so that user 1 owns it, noone else can do anything.
-setid 0
-setperm /dir 1 NONE
-expect 1 NONE
-getperm /dir
-expect test
-expect test2
-dir /dir
-write /dir/test3 contents
-
-# User 2 can do nothing. Can't even tell if file exists.
-setid 2
-expect setperm failed: Permission denied
-setperm /dir 2 NONE
-expect getperm failed: Permission denied
-getperm /dir
-expect dir failed: Permission denied
-dir /dir
-expect read failed: Permission denied
-read /dir/test
-expect read failed: Permission denied
-read /dir/test2
-expect read failed: Permission denied
-read /dir/test3
-expect read failed: Permission denied
-read /dir/test4
-expect write failed: Permission denied
-write /dir/test contents
-expect write failed: Permission denied
-write /dir/test4 contents
-
-# Tools can always access things.
-setid 0
-expect 1 NONE
-getperm /dir
-expect test
-expect test2
-expect test3
-dir /dir
-write /dir/test4 contents
-
-# Inherited by child.
-mkdir /dir/subdir
-expect 1 NONE
-getperm /dir/subdir
-write /dir/subfile contents
-expect 1 NONE
-getperm /dir/subfile
-
-# But for domains, they own it.
-setperm /dir/subdir 2 READ/WRITE
-expect 2 READ/WRITE
-getperm /dir/subdir
-setid 3
-write /dir/subdir/subfile contents
-expect 3 READ/WRITE
-getperm /dir/subdir/subfile
-
-# Inheritence works through multiple directories, too.
-write /dir/subdir/1/2/3/4 contents
-expect 3 READ/WRITE
-getperm /dir/subdir/1/2/3/4
-mkdir /dir/subdir/a/b/c/d
-expect 3 READ/WRITE
-getperm /dir/subdir/a/b/c/d
diff --git a/tools/xenstore/testsuite/07watch.test b/tools/xenstore/testsuite/07watch.test
deleted file mode 100644
index b4a44adebc..0000000000
--- a/tools/xenstore/testsuite/07watch.test
+++ /dev/null
@@ -1,176 +0,0 @@
-# Watch something, write to it, check watch has fired.
-write /test contents
-
-1 watch /test token
-2 write /test contents2
-expect 1:/test:token
-1 waitwatch
-1 close
-
-# Check that reads don't set it off.
-1 watch /test token
-expect 2:contents2
-2 read /test
-expect 1: waitwatch failed: Connection timed out
-1 waitwatch
-1 close
-
-# mkdir, setperm and rm should (also tests watching dirs)
-mkdir /dir
-1 watch /dir token
-2 mkdir /dir/newdir
-expect 1:/dir/newdir:token
-1 waitwatch
-2 setperm /dir/newdir 0 READ
-expect 1:/dir/newdir:token
-1 waitwatch
-2 rm /dir/newdir
-expect 1:/dir/newdir:token
-1 waitwatch
-1 close
-2 close
-
-# Changed in b594bb976a743d509f1ffabb5bc698874ab90d8f
-## We don't get a watch from our own commands.
-#watch /dir token
-#mkdir /dir/newdir
-#expect waitwatch failed: Connection timed out
-#waitwatch
-#close
-
-# ignore watches while doing commands, should work.
-watch /dir token
-1 write /dir/test contents
-expect contents
-read /dir/test
-expect /dir/test:token
-waitwatch
-close
-
-# watch priority test: all simultaneous
-1 watch /dir token1
-3 watch /dir token3
-2 watch /dir token2
-write /dir/test contents
-expect 3:/dir/test:token3
-3 waitwatch
-expect 2:/dir/test:token2
-2 waitwatch
-expect 1:/dir/test:token1
-1 waitwatch
-1 close
-2 close
-3 close
-
-# If one dies (without acking), the other should still get ack.
-1 watch /dir token1
-2 watch /dir token2
-write /dir/test contents
-expect 2:/dir/test:token2
-2 waitwatch
-2 close
-expect 1:/dir/test:token1
-1 waitwatch
-1 close
-
-# If one dies (without reading at all), the other should still get ack.
-1 watch /dir token1
-2 watch /dir token2
-write /dir/test contents
-2 close
-expect 1:/dir/test:token1
-1 waitwatch
-1 close
-2 close
-
-# unwatch
-1 watch /dir token1
-1 unwatch /dir token1
-1 watch /dir token2
-2 write /dir/test2 contents
-expect 1:/dir/test2:token2
-1 waitwatch
-1 unwatch /dir token2
-1 close
-2 close
-
-# unwatch while watch pending. Other watcher still gets the event.
-1 watch /dir token1
-2 watch /dir token2
-write /dir/test contents
-2 unwatch /dir token2
-expect 1:/dir/test:token1
-1 waitwatch
-1 close
-2 close
-
-# unwatch while watch pending. Should clear this so we get next event.
-1 watch /dir token1
-write /dir/test contents
-1 unwatch /dir token1
-1 watch /dir/test token2
-write /dir/test contents2
-expect 1:/dir/test:token2
-1 waitwatch
-
-# check we only get notified once.
-1 watch /test token
-2 write /test contents2
-expect 1:/test:token
-1 waitwatch
-expect 1: waitwatch failed: Connection timed out
-1 waitwatch
-1 close
-
-# watches are queued in order.
-1 watch / token
-2 write /test1 contents
-2 write /test2 contents
-2 write /test3 contents
-expect 1:/test1:token
-1 waitwatch
-expect 1:/test2:token
-1 waitwatch
-expect 1:/test3:token
-1 waitwatch
-1 close
-
-# Creation of subpaths should be covered correctly.
-1 watch / token
-2 write /test/subnode contents2
-2 write /test/subnode/subnode contents2
-expect 1:/test/subnode:token
-1 waitwatch
-expect 1:/test/subnode/subnode:token
-1 waitwatch
-expect 1: waitwatch failed: Connection timed out
-1 waitwatch
-1 close
-
-# Watch event must have happened before we registered interest.
-1 watch / token
-2 write /test/subnode contents2
-1 watchnoack / token2 0
-expect 1:/test/subnode:token
-1 waitwatch
-expect 1:/:token2
-1 waitwatch
-expect 1: waitwatch failed: Connection timed out
-1 waitwatch
-1 close
-
-# Rm fires notification on child.
-1 watch /test/subnode token
-2 rm /test
-expect 1:/test/subnode:token
-1 waitwatch
-
-# Watch should not double-send after we ack, even if we did something in between.
-1 watch /test2 token
-2 write /test2/foo contents2
-expect 1:/test2/foo:token
-1 waitwatch
-expect 1:contents2
-1 read /test2/foo
-expect 1: waitwatch failed: Connection timed out
-1 waitwatch
diff --git a/tools/xenstore/testsuite/08transaction.slowtest b/tools/xenstore/testsuite/08transaction.slowtest
deleted file mode 100644
index 0e01ef27dc..0000000000
--- a/tools/xenstore/testsuite/08transaction.slowtest
+++ /dev/null
@@ -1,43 +0,0 @@
-# Test transaction clashes.
-
-mkdir /test
-write /test/entry1 contents
-
-# Start transaction, do read-only op, transaction succeeds
-1 start
-1 write /test/entry1 contents2
-expect contents
-read /test/entry1
-1 commit
-expect contents2
-read /test/entry1
-
-# Start transaction, abort other transaction, transaction succeeds.
-1 start
-1 write /test/entry1 contents3
-start
-write /test/entry1 contents
-abort
-1 commit
-expect contents3
-read /test/entry1
-
-# Start transaction, do write op, transaction fails
-1 start
-1 write /test/entry1 contents4
-write /test/entry1 contents
-expect 1: commit failed: Resource temporarily unavailable
-1 commit
-expect contents
-read /test/entry1
-
-# Start transaction, do other transaction, transaction fails
-1 start
-1 write /test/entry1 contents4
-start
-write /test/entry1 contents5
-commit
-expect 1: commit failed: Resource temporarily unavailable
-1 commit
-expect contents5
-read /test/entry1
diff --git a/tools/xenstore/testsuite/08transaction.test b/tools/xenstore/testsuite/08transaction.test
deleted file mode 100644
index c65fb647fa..0000000000
--- a/tools/xenstore/testsuite/08transaction.test
+++ /dev/null
@@ -1,92 +0,0 @@
-# Test transactions.
-
-mkdir /test
-
-# Simple transaction: create a file inside transaction.
-1 start
-1 write /test/entry1 contents
-2 dir /test
-expect 1:entry1
-1 dir /test
-1 commit
-expect 2:contents
-2 read /test/entry1
-
-rm /test/entry1
-
-# Create a file and abort transaction.
-1 start
-1 write /test/entry1 contents
-2 dir /test
-expect 1:entry1
-1 dir /test
-1 abort
-2 dir /test
-
-write /test/entry1 contents
-# Delete in transaction, commit
-1 start
-1 rm /test/entry1
-expect 2:entry1
-2 dir /test
-1 dir /test
-1 commit
-2 dir /test
-
-# Delete in transaction, abort.
-write /test/entry1 contents
-1 start
-1 rm /test/entry1
-expect 2:entry1
-2 dir /test
-1 dir /test
-1 abort
-expect 2:entry1
-2 dir /test
-
-# Events inside transactions don't trigger watches until (successful) commit.
-mkdir /test/dir
-1 watch /test token
-2 start
-2 mkdir /test/dir/sub
-expect 1: waitwatch failed: Connection timed out
-1 waitwatch
-2 close
-1 close
-
-1 watch /test token
-2 start
-2 mkdir /test/dir/sub
-2 abort
-expect 1: waitwatch failed: Connection timed out
-1 waitwatch
-1 close
-
-1 watch /test token
-2 start
-2 mkdir /test/dir/sub
-2 commit
-expect 1:/test/dir/sub:token
-1 waitwatch
-1 close
-
-# Rm inside transaction works like rm outside: children get notified.
-1 watch /test/dir/sub token
-2 start
-2 rm /test/dir
-2 commit
-expect 1:/test/dir/sub:token
-1 waitwatch
-1 close
-
-# Multiple events from single transaction don't trigger assert
-1 watch /test token
-2 start
-2 write /test/1 contents
-2 write /test/2 contents
-2 commit
-expect 1:/test/1:token
-1 waitwatch
-expect 1:/test/2:token
-1 waitwatch
-1 close
diff --git a/tools/xenstore/testsuite/09domain.test b/tools/xenstore/testsuite/09domain.test
deleted file mode 100644
index 0f30679d2e..0000000000
--- a/tools/xenstore/testsuite/09domain.test
+++ /dev/null
@@ -1,19 +0,0 @@
-# Test domain communication.
-
-# Create a domain, write an entry.
-expect handle is 1
-introduce 1 100 7 /my/home
-1 write /entry1 contents
-expect entry1
-expect tool
-dir /
-close
-
-# Release that domain.
-release 1
-close
-
-# Introduce and release by same connection.
-expect handle is 2
-introduce 1 100 7 /my/home
-release 1
diff --git a/tools/xenstore/testsuite/10domain-homedir.test b/tools/xenstore/testsuite/10domain-homedir.test
deleted file mode 100644
index 88e4672909..0000000000
--- a/tools/xenstore/testsuite/10domain-homedir.test
+++ /dev/null
@@ -1,18 +0,0 @@
-# Test domain "implicit" paths.
-
-# Create a domain, write an entry using implicit path, read using implicit
-mkdir /home
-expect handle is 1
-introduce 1 100 7 /home
-1 write entry1 contents
-expect contents
-read /home/entry1
-expect entry1
-dir /home
-
-# Place a watch using a relative path: expect relative answer.
-1 mkdir foo
-1 watch foo token
-write /home/foo/bar contents
-expect 1:foo/bar:token
-1 waitwatch
diff --git a/tools/xenstore/testsuite/11domain-watch.test b/tools/xenstore/testsuite/11domain-watch.test
deleted file mode 100644
index 3b28ee3094..0000000000
--- a/tools/xenstore/testsuite/11domain-watch.test
+++ /dev/null
@@ -1,50 +0,0 @@
-# Test watching from a domain.
-
-# Watch something, write to it, check watch has fired.
-write /test contents
-mkdir /dir
-
-expect handle is 1
-introduce 1 100 7 /my/home
-1 watch /test token
-write /test contents2
-expect 1:/test:token
-1 waitwatch
-1 unwatch /test token
-release 1
-1 close
-
-# ignore watches while doing commands, should work.
-expect handle is 1
-introduce 1 100 7 /my/home
-1 watch /dir token
-write /dir/test contents
-1 write /dir/test2 contents2
-1 write /dir/test3 contents3
-1 write /dir/test4 contents4
-expect 1:/dir/test:token
-1 waitwatch
-release 1
-1 close
-
-# unwatch
-expect handle is 1
-introduce 1 100 7 /my/home
-1 watch /dir token1
-1 unwatch /dir token1
-1 watch /dir token2
-write /dir/test2 contents
-expect 1:/dir/test2:token2
-1 waitwatch
-1 unwatch /dir token2
-release 1
-1 close
-
-# unwatch while watch pending.
-expect handle is 1
-introduce 1 100 7 /my/home
-1 watch /dir token1
-write /dir/test2 contents
-1 unwatch /dir token1
-release 1
-1 close
diff --git a/tools/xenstore/testsuite/12readonly.test b/tools/xenstore/testsuite/12readonly.test
deleted file mode 100644
index 14878e7dc1..0000000000
--- a/tools/xenstore/testsuite/12readonly.test
+++ /dev/null
@@ -1,38 +0,0 @@
-# Test that read only connection can't alter store.
-
-write /test contents
-
-readonly
-expect test
-expect tool
-dir /
-
-expect contents
-read /test
-expect 0 READ
-getperm /test
-watch /test token
-unwatch /test token
-start
-commit
-start
-abort
-
-# These don't work
-expect write failed: Permission denied
-write /test2 contents
-expect write failed: Permission denied
-write /test contents
-expect setperm failed: Permission denied
-setperm /test 100 NONE
-expect setperm failed: Permission denied
-setperm /test 100 NONE
-expect introduce failed: Permission denied
-introduce 1 100 7 /home
-
-# Check that watches work like normal.
-watch / token
-1 readwrite
-1 write /test contents
-expect /test:token
-waitwatch
diff --git a/tools/xenstore/testsuite/13watch-ack.test b/tools/xenstore/testsuite/13watch-ack.test
deleted file mode 100644
index e15f2b85e3..0000000000
--- a/tools/xenstore/testsuite/13watch-ack.test
+++ /dev/null
@@ -1,21 +0,0 @@
-# This demonstrates a bug where an xs_acknowledge_watch returns
-# EINVAL, because the daemon doesn't track what watch event it sent
-# and relies on it being the "first" watch which has an event.
-# Watches firing after the first event is sent out will change this.
-
-# Create three things to watch.
-mkdir /test
-mkdir /test/1
-mkdir /test/2
-mkdir /test/3
-
-# Watch all three, fire event on 2, read watch, fire event on 1 and 3, ack 2.
-1 watch /test/1 token1
-1 watch /test/2 token2
-1 watch /test/3 token3
-2 write /test/2 contents2
-expect 1:/test/2:token2
-1 waitwatch
-3 write /test/1 contents1
-4 write /test/3 contents3
-1 close
diff --git a/tools/xenstore/testsuite/14complexperms.test b/tools/xenstore/testsuite/14complexperms.test
deleted file mode 100644
index 033dc00b45..0000000000
--- a/tools/xenstore/testsuite/14complexperms.test
+++ /dev/null
@@ -1,68 +0,0 @@
-# We should not be able to tell the difference between a node which
-# doesn't exist, and a node we don't have permission on, if we don't
-# have permission on it directory.
-
-mkdir /dir
-setperm /dir 0 NONE
-
-# First when it doesn't exist
-setid 1
-expect *Permission denied
-dir /dir/file
-expect *Permission denied
-read /dir/file
-expect *Permission denied
-write /dir/file value
-expect *Permission denied
-mkdir /dir/file
-expect *Permission denied
-rm /dir/file
-expect *Permission denied
-rm /dir
-expect *Permission denied
-getperm /dir/file
-expect *Permission denied
-setperm /dir/file 0 NONE
-# We get no watch event when there's no permission. It's a corner case.
-watchnoack /dir/file token
-1 write /dir/file contents
-1 rm /dir/file
-expect waitwatch failed: Connection timed out
-waitwatch
-unwatch /dir/file token
-expect *No such file or directory
-unwatch /dir/file token
-expect *Permission denied
-introduce 2 100 7 /dir/file
-
-# Now it exists
-setid 0
-write /dir/file contents
-
-setid 1
-expect *Permission denied
-dir /dir/file
-expect *Permission denied
-read /dir/file
-expect *Permission denied
-write /dir/file value
-expect *Permission denied
-mkdir /dir/file
-expect *Permission denied
-rm /dir/file
-expect *Permission denied
-rm /dir
-expect *Permission denied
-getperm /dir/file
-expect *Permission denied
-setperm /dir/file 0 NONE
-watchnoack /dir/file token
-1 write /dir/file contents
-1 rm /dir/file
-expect waitwatch failed: Connection timed out
-waitwatch
-unwatch /dir/file token
-expect *No such file or directory
-unwatch /dir/file token
-expect *Permission denied
-introduce 2 100 7 /dir/file
diff --git a/tools/xenstore/testsuite/test.sh b/tools/xenstore/testsuite/test.sh
deleted file mode 100755
index 2a428d2128..0000000000
--- a/tools/xenstore/testsuite/test.sh
+++ /dev/null
@@ -1,64 +0,0 @@
-#! /bin/sh
-
-set -e
-set -m
-
-run_test()
-{
- rm -rf $XENSTORED_ROOTDIR
- mkdir $XENSTORED_ROOTDIR
- if [ $VALGRIND -eq 1 ]; then
- valgrind --suppressions=testsuite/vg-suppressions -q ./xenstored_test --output-pid --trace-file=testsuite/tmp/trace --no-fork > /tmp/pid 2> testsuite/tmp/xenstored_errors &
- while [ ! -s /tmp/pid ]; do sleep 0; done
- PID=`cat /tmp/pid`
- rm /tmp/pid
- else
- # We don't get error messages from this, though.
- PID=`./xenstored_test --output-pid --trace-file=testsuite/tmp/trace`
- fi
- if ./xs_test $2 $1; then
- if [ -s testsuite/tmp/xenstored_errors ]; then
- kill $PID
- echo Errors:
- cat testsuite/tmp/xenstored_errors
- return 1
- fi
- kill $PID
- sleep 1
- return 0
- else
- # In case daemon is wedged.
- kill $PID
- sleep 1
- return 1
- fi
-}
-
-if [ x$1 = x--fast ]; then
- VALGRIND=0
- SLOWTESTS=""
- shift
-else
- if type valgrind >/dev/null 2>&1; then
- VALGRIND=1
- else
- echo "WARNING: valgrind not available" >&2
- VALGRIND=0
- fi
- SLOWTESTS=testsuite/[0-9]*.slowtest
-fi
-
-MATCH=${1:-"*"}
-for f in testsuite/[0-9]*.test $SLOWTESTS; do
- case `basename $f` in $MATCH) RUN=1;; esac
- [ -n "$RUN" ] || continue
-
- if run_test $f -x >/tmp/out; then
- echo -n .
- else
- cat /tmp/out
- # That will have filled the screen, repeat message.
- echo Test $f failed
- exit 1
- fi
-done
diff --git a/tools/xenstore/testsuite/vg-suppressions b/tools/xenstore/testsuite/vg-suppressions
deleted file mode 100644
index b844764ef8..0000000000
--- a/tools/xenstore/testsuite/vg-suppressions
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- Glibc goes boom from _start (Debian glibc 2.3.5-3)
- Memcheck:Cond
- obj:/lib/ld-2.3.5.so
- obj:/lib/ld-2.3.5.so
- obj:/lib/ld-2.3.5.so
- obj:/lib/ld-2.3.5.so
- obj:/lib/ld-2.3.5.so
-}
diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
index 0a800c7fe3..f576c1c83f 100644
--- a/tools/xenstore/xenstored_core.c
+++ b/tools/xenstore/xenstored_core.c
@@ -39,7 +39,6 @@
#include <assert.h>
#include <setjmp.h>
-//#define DEBUG
#include "utils.h"
#include "list.h"
#include "talloc.h"
@@ -53,7 +52,6 @@
#include "hashtable.h"
-
extern int xce_handle; /* in xenstored_domain.c */
static bool verbose = false;
@@ -82,50 +80,6 @@ int quota_nb_watch_per_domain = 128;
int quota_max_entry_size = 2048; /* 2K */
int quota_max_transaction = 10;
-#ifdef TESTING
-static bool failtest = false;
-
-/* We override talloc's malloc. */
-void *test_malloc(size_t size)
-{
- /* 1 in 20 means only about 50% of connections establish. */
- if (failtest && (random() % 32) == 0)
- return NULL;
- return malloc(size);
-}
-
-static void stop_failtest(int signum __attribute__((unused)))
-{
- failtest = false;
-}
-
-/* Need these before we #define away write_all/mkdir in testing.h */
-bool test_write_all(int fd, void *contents, unsigned int len);
-bool test_write_all(int fd, void *contents, unsigned int len)
-{
- if (failtest && (random() % 8) == 0) {
- if (len)
- len = random() % len;
- write(fd, contents, len);
- errno = ENOSPC;
- return false;
- }
- return xs_write_all(fd, contents, len);
-}
-
-int test_mkdir(const char *dir, int perms);
-int test_mkdir(const char *dir, int perms)
-{
- if (failtest && (random() % 8) == 0) {
- errno = ENOSPC;
- return -1;
- }
- return mkdir(dir, perms);
-}
-#endif /* TESTING */
-
-#include "xenstored_test.h"
-
TDB_CONTEXT *tdb_context(struct connection *conn)
{
/* conn = NULL used in manual_node at setup. */
@@ -1163,12 +1117,10 @@ static void do_debug(struct connection *conn, struct buffered_data *in)
{
int num;
-#ifndef TESTING
if (conn->id != 0) {
send_error(conn, EACCES);
return;
}
-#endif
num = xs_count_strings(in->buffer, in->used);
@@ -1179,18 +1131,10 @@ static void do_debug(struct connection *conn, struct buffered_data *in)
}
xprintf("debug: %s", in->buffer + get_string(in, 0));
}
+
if (streq(in->buffer, "check"))
check_store();
-#ifdef TESTING
- /* For testing, we allow them to set id. */
- if (streq(in->buffer, "setid")) {
- conn->id = atoi(in->buffer + get_string(in, 0));
- } else if (streq(in->buffer, "failtest")) {
- if (get_string(in, 0) < in->used)
- srandom(atoi(in->buffer + get_string(in, 0)));
- failtest = true;
- }
-#endif /* TESTING */
+
send_ack(conn, XS_DEBUG);
}
@@ -1319,10 +1263,8 @@ static void handle_input(struct connection *conn)
return;
if (in->hdr.msg.len > PATH_MAX) {
-#ifndef TESTING
syslog(LOG_ERR, "Client tried to feed us %i",
in->hdr.msg.len);
-#endif
goto bad_client;
}
@@ -1414,39 +1356,7 @@ static void accept_connection(int sock, bool canwrite)
close(fd);
}
-#ifdef TESTING
-/* Valgrind can check our writes better if we don't use mmap */
-#define TDB_FLAGS TDB_NOMMAP
-/* Useful for running under debugger. */
-void dump_connection(void)
-{
- struct connection *i;
-
- list_for_each_entry(i, &connections, list) {
- printf("Connection %p:\n", i);
- printf(" state = %s\n",
- list_empty(&i->out_list) ? "OK" : "BUSY");
- if (i->id)
- printf(" id = %i\n", i->id);
- if (!i->in->inhdr || i->in->used)
- printf(" got %i bytes of %s\n",
- i->in->used, i->in->inhdr ? "header" : "data");
-#if 0
- if (i->out)
- printf(" sending message %s (%s) out\n",
- sockmsg_string(i->out->hdr.msg.type),
- i->out->buffer);
- if (i->transaction)
- dump_transaction(i);
- if (i->domain)
- dump_domain(i);
-#endif
- dump_watches(i);
- }
-}
-#else
#define TDB_FLAGS 0
-#endif
/* We create initial nodes manually. */
static void manual_node(const char *name, const char *child)
@@ -1693,10 +1603,6 @@ static void corrupt(struct connection *conn, const char *fmt, ...)
log("corruption detected by connection %i: err %s: %s",
conn ? (int)conn->id : -1, strerror(saved_errno), str);
-#ifdef TESTING
- /* Allow them to attach debugger. */
- sleep(30);
-#endif
check_store();
}
@@ -1740,11 +1646,10 @@ static void daemonize(void)
if (pid != 0)
exit(0);
-#ifndef TESTING /* Relative paths for socket names */
/* Move off any mount points we might be in. */
if (chdir("/") == -1)
barf_perror("Failed to chdir");
-#endif
+
/* Discard our parent's old-fashioned umask prejudices. */
umask(0);
}
@@ -1941,10 +1846,6 @@ int main(int argc, char *argv[])
signal(SIGHUP, trigger_reopen_log);
-#ifdef TESTING
- signal(SIGUSR1, stop_failtest);
-#endif
-
if (xce_handle != -1)
evtchn_fd = xc_evtchn_fd(xce_handle);
diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c
index 6df0c32c64..0f6e11a29c 100644
--- a/tools/xenstore/xenstored_domain.c
+++ b/tools/xenstore/xenstored_domain.c
@@ -23,14 +23,12 @@
#include <stdlib.h>
#include <stdarg.h>
-//#define DEBUG
#include "utils.h"
#include "talloc.h"
#include "xenstored_core.h"
#include "xenstored_domain.h"
#include "xenstored_transaction.h"
#include "xenstored_watch.h"
-#include "xenstored_test.h"
#include <xenctrl.h>
@@ -217,10 +215,8 @@ void handle_event(void)
if (port == virq_port)
domain_cleanup();
-#ifndef TESTING
if (xc_evtchn_unmask(xce_handle, port) == -1)
barf_perror("Failed to write to event fd");
-#endif
}
bool domain_can_read(struct connection *conn)
diff --git a/tools/xenstore/xenstored_test.h b/tools/xenstore/xenstored_test.h
deleted file mode 100644
index cf607cf2e0..0000000000
--- a/tools/xenstore/xenstored_test.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- Testing replcements for Xen Store Daemon.
- Copyright (C) 2005 Rusty Russell IBM Corporation
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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 _XENSTORED_TEST_H
-#define _XENSTORED_TEST_H
-
-#ifdef TESTING
-bool test_write_all(int fd, void *contents, unsigned int len);
-#define xs_write_all test_write_all
-
-int test_mkdir(const char *dir, int perms);
-#define mkdir test_mkdir
-
-int fake_open_eventchn(void);
-void fake_block_events(void);
-void fake_ack_event(void);
-
-#define ioctl(a,b,c) 0
-
-#endif
-
-#endif /* _XENSTORED_INTERNAL_H */
diff --git a/tools/xenstore/xenstored_transaction.c b/tools/xenstore/xenstored_transaction.c
index 0270301396..f079bdc7e1 100644
--- a/tools/xenstore/xenstored_transaction.c
+++ b/tools/xenstore/xenstored_transaction.c
@@ -35,7 +35,6 @@
#include "xenstored_domain.h"
#include "xs_lib.h"
#include "utils.h"
-#include "xenstored_test.h"
struct changed_node
{
diff --git a/tools/xenstore/xenstored_watch.c b/tools/xenstore/xenstored_watch.c
index 4d1a6d5bfb..27e082a24f 100644
--- a/tools/xenstore/xenstored_watch.c
+++ b/tools/xenstore/xenstored_watch.c
@@ -29,7 +29,6 @@
#include "xenstored_watch.h"
#include "xs_lib.h"
#include "utils.h"
-#include "xenstored_test.h"
#include "xenstored_domain.h"
extern int quota_nb_watch_per_domain;
@@ -196,17 +195,6 @@ void conn_delete_all_watches(struct connection *conn)
}
}
-#ifdef TESTING
-void dump_watches(struct connection *conn)
-{
- struct watch *watch;
-
- list_for_each_entry(watch, &conn->watches, list)
- printf(" watch on %s token %s\n",
- watch->node, watch->token);
-}
-#endif
-
/*
* Local variables:
* c-file-style: "linux"
diff --git a/tools/xenstore/xs_crashme.c b/tools/xenstore/xs_crashme.c
deleted file mode 100644
index ea5bd92509..0000000000
--- a/tools/xenstore/xs_crashme.c
+++ /dev/null
@@ -1,393 +0,0 @@
-/* Code which randomly corrupts bits going to the daemon.
- Copyright (C) 2005 Rusty Russell IBM Corporation
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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 <stdbool.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <stdarg.h>
-#include <string.h>
-#include <sys/time.h>
-#include "xs.h"
-#include "talloc.h"
-#include <errno.h>
-
-#define XSTEST
-#define RAND_FREQ 128 /* One char in 32 is corrupted. */
-
-/* jhash.h: Jenkins hash support.
- *
- * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
- *
- * http://burtleburtle.net/bob/hash/
- *
- * These are the credits from Bob's sources:
- *
- * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
- * hash(), hash2(), hash3, and mix() are externally useful functions.
- * Routines to test the hash are included if SELF_TEST is defined.
- * You can use this free for any purpose. It has no warranty.
- *
- * Copyright (C) 2003 David S. Miller (davem@redhat.com)
- *
- * I've modified Bob's hash to be useful in the Linux kernel, and
- * any bugs present are surely my fault. -DaveM
- */
-
-/* NOTE: Arguments are modified. */
-#define __jhash_mix(a, b, c) \
-{ \
- a -= b; a -= c; a ^= (c>>13); \
- b -= c; b -= a; b ^= (a<<8); \
- c -= a; c -= b; c ^= (b>>13); \
- a -= b; a -= c; a ^= (c>>12); \
- b -= c; b -= a; b ^= (a<<16); \
- c -= a; c -= b; c ^= (b>>5); \
- a -= b; a -= c; a ^= (c>>3); \
- b -= c; b -= a; b ^= (a<<10); \
- c -= a; c -= b; c ^= (b>>15); \
-}
-
-/* The golden ration: an arbitrary value */
-#define JHASH_GOLDEN_RATIO 0x9e3779b9
-
-/* The most generic version, hashes an arbitrary sequence
- * of bytes. No alignment or length assumptions are made about
- * the input key.
- */
-static inline uint32_t jhash(const void *key, uint32_t length, uint32_t initval)
-{
- uint32_t a, b, c, len;
- const uint8_t *k = key;
-
- len = length;
- a = b = JHASH_GOLDEN_RATIO;
- c = initval;
-
- while (len >= 12) {
- a += (k[0] +((uint32_t)k[1]<<8) +((uint32_t)k[2]<<16) +((uint32_t)k[3]<<24));
- b += (k[4] +((uint32_t)k[5]<<8) +((uint32_t)k[6]<<16) +((uint32_t)k[7]<<24));
- c += (k[8] +((uint32_t)k[9]<<8) +((uint32_t)k[10]<<16)+((uint32_t)k[11]<<24));
-
- __jhash_mix(a,b,c);
-
- k += 12;
- len -= 12;
- }
-
- c += length;
- switch (len) {
- case 11: c += ((uint32_t)k[10]<<24);
- case 10: c += ((uint32_t)k[9]<<16);
- case 9 : c += ((uint32_t)k[8]<<8);
- case 8 : b += ((uint32_t)k[7]<<24);
- case 7 : b += ((uint32_t)k[6]<<16);
- case 6 : b += ((uint32_t)k[5]<<8);
- case 5 : b += k[4];
- case 4 : a += ((uint32_t)k[3]<<24);
- case 3 : a += ((uint32_t)k[2]<<16);
- case 2 : a += ((uint32_t)k[1]<<8);
- case 1 : a += k[0];
- };
-
- __jhash_mix(a,b,c);
-
- return c;
-}
-
-/* A special optimized version that handles 1 or more of uint32_ts.
- * The length parameter here is the number of uint32_ts in the key.
- */
-static inline uint32_t jhash2(uint32_t *k, uint32_t length, uint32_t initval)
-{
- uint32_t a, b, c, len;
-
- a = b = JHASH_GOLDEN_RATIO;
- c = initval;
- len = length;
-
- while (len >= 3) {
- a += k[0];
- b += k[1];
- c += k[2];
- __jhash_mix(a, b, c);
- k += 3; len -= 3;
- }
-
- c += length * 4;
-
- switch (len) {
- case 2 : b += k[1];
- case 1 : a += k[0];
- };
-
- __jhash_mix(a,b,c);
-
- return c;
-}
-
-
-/* A special ultra-optimized versions that knows they are hashing exactly
- * 3, 2 or 1 word(s).
- *
- * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
- * done at the end is not done here.
- */
-static inline uint32_t jhash_3words(uint32_t a, uint32_t b, uint32_t c, uint32_t initval)
-{
- a += JHASH_GOLDEN_RATIO;
- b += JHASH_GOLDEN_RATIO;
- c += initval;
-
- __jhash_mix(a, b, c);
-
- return c;
-}
-
-static inline uint32_t jhash_2words(uint32_t a, uint32_t b, uint32_t initval)
-{
- return jhash_3words(a, b, 0, initval);
-}
-
-static inline uint32_t jhash_1word(uint32_t a, uint32_t initval)
-{
- return jhash_3words(a, 0, 0, initval);
-}
-
-static unsigned int get_randomness(int *state)
-{
- return jhash_1word((*state)++, *state * 1103515243);
-}
-
-static int state;
-
-/* Lengthening headers is pointless: other end will just wait for more
- * data and timeout. We merely shorten the length. */
-static void corrupt_header(char *output, const struct xsd_sockmsg *msg,
- unsigned int *next_bit)
-{
- struct xsd_sockmsg newmsg = *msg;
-
- while (*next_bit < sizeof(*msg)) {
- if (newmsg.len)
- newmsg.len = get_randomness(&state) % newmsg.len;
- *next_bit += get_randomness(&state) % RAND_FREQ;
- }
- memcpy(output, &newmsg, sizeof(newmsg));
-}
-
-#define read_all_choice read_all
-static bool write_all_choice(int fd, const void *data, unsigned int len)
-{
- char corrupt_data[len];
- bool ret;
- static unsigned int next_bit;
-
- if (len == sizeof(struct xsd_sockmsg)
- && ((unsigned long)data % __alignof__(struct xsd_sockmsg)) == 0)
- corrupt_header(corrupt_data, data, &next_bit);
- else {
- memcpy(corrupt_data, data, len);
- while (next_bit < len * CHAR_BIT) {
- corrupt_data[next_bit/CHAR_BIT]
- ^= (1 << (next_bit%CHAR_BIT));
- next_bit += get_randomness(&state) % RAND_FREQ;
- }
- }
-
- ret = xs_write_all(fd, corrupt_data, len);
- next_bit -= len * CHAR_BIT;
- return ret;
-}
-
-#include "xs.c"
-
-static char *random_path(void)
-{
- unsigned int i;
- char *ret = NULL;
-
- if (get_randomness(&state) % 20 == 0)
- return talloc_strdup(NULL, "/");
-
- for (i = 0; i < 1 || (get_randomness(&state) % 2); i++) {
- ret = talloc_asprintf_append(ret, "/%i",
- get_randomness(&state) % 15);
- }
- return ret;
-}
-
-/* Do the next operation, return the results. */
-static void do_next_op(struct xs_handle *h, bool verbose)
-{
- char *name;
- unsigned int num;
-
- if (verbose)
- printf("State %i: ", state);
-
- name = random_path();
- switch (get_randomness(&state) % 9) {
- case 0:
- if (verbose)
- printf("DIR %s\n", name);
- free(xs_directory(h, name, &num));
- break;
- case 1:
- if (verbose)
- printf("READ %s\n", name);
- free(xs_read(h, name, &num));
- break;
- case 2: {
- char *contents = talloc_asprintf(NULL, "%i",
- get_randomness(&state));
- unsigned int len = get_randomness(&state)%(strlen(contents)+1);
- if (verbose)
- printf("WRITE %s %.*s\n", name, len, contents);
- xs_write(h, name, contents, len);
- break;
- }
- case 3:
- if (verbose)
- printf("MKDIR %s\n", name);
- xs_mkdir(h, name);
- break;
- case 4:
- if (verbose)
- printf("RM %s\n", name);
- xs_rm(h, name);
- break;
- case 5:
- if (verbose)
- printf("GETPERMS %s\n", name);
- free(xs_get_permissions(h, name, &num));
- break;
- case 6: {
- unsigned int i, num = get_randomness(&state)%8;
- struct xs_permissions perms[num];
-
- if (verbose)
- printf("SETPERMS %s: ", name);
- for (i = 0; i < num; i++) {
- perms[i].id = get_randomness(&state)%8;
- perms[i].perms = get_randomness(&state)%4;
- if (verbose)
- printf("%i%c ", perms[i].id,
- perms[i].perms == XS_PERM_WRITE ? 'W'
- : perms[i].perms == XS_PERM_READ ? 'R'
- : perms[i].perms ==
- (XS_PERM_READ|XS_PERM_WRITE) ? 'B'
- : 'N');
- }
- if (verbose)
- printf("\n");
- xs_set_permissions(h, name, perms, num);
- break;
- }
- case 7: {
- if (verbose)
- printf("START %s\n", name);
- xs_transaction_start(h);
- break;
- }
- case 8: {
- bool abort = (get_randomness(&state) % 2);
-
- if (verbose)
- printf("STOP %s\n", abort ? "ABORT" : "COMMIT");
- xs_transaction_end(h, abort);
- break;
- }
- default:
- barf("Impossible randomness");
- }
-}
-
-static struct xs_handle *h;
-static void alarmed(int sig __attribute__((unused)))
-{
- /* We force close on timeout. */
- close(h->fd);
-}
-
-static int start_daemon(void)
-{
- int fds[2];
- int daemon_pid;
-
- /* Start daemon. */
- pipe(fds);
- if ((daemon_pid = fork())) {
- /* Child writes PID when its ready: we wait for that. */
- char buffer[20];
- close(fds[1]);
- if (read(fds[0], buffer, sizeof(buffer)) < 0)
- barf("Failed to summon daemon");
- close(fds[0]);
- return daemon_pid;
- } else {
- dup2(fds[1], STDOUT_FILENO);
- close(fds[0]);
-#if 1
- execlp("valgrind", "valgrind", "--log-file=/tmp/xs_crashme.vglog", "-q", "./xenstored_test", "--output-pid",
- "--no-fork", "--trace-file=/tmp/trace", NULL);
-#else
- execlp("./xenstored_test", "xenstored_test", "--output-pid",
- "--no-fork", NULL);
-#endif
- exit(1);
- }
-}
-
-
-int main(int argc, char **argv)
-{
- unsigned int i;
- int pid;
-
- if (argc != 3 && argc != 4)
- barf("Usage: xs_crashme <iterations> <seed> [pid]");
-
- if (argc == 3)
- pid = start_daemon();
- else
- pid = atoi(argv[3]);
-
- state = atoi(argv[2]);
- h = xs_daemon_open();
- if (!h)
- barf_perror("Opening connection to daemon");
- signal(SIGALRM, alarmed);
- for (i = 0; i < (unsigned)atoi(argv[1]); i++) {
- alarm(1);
- do_next_op(h, false);
- if (i % (atoi(argv[1]) / 72 ?: 1) == 0) {
- printf(".");
- fflush(stdout);
- }
- if (kill(pid, 0) != 0)
- barf_perror("Pinging daemon on iteration %i", i);
- if (h->fd < 0) {
- xs_daemon_close(h);
- h = xs_daemon_open();
- if (!h)
- barf_perror("Connecting on iteration %i", i);
- }
- }
- kill(pid, SIGTERM);
- return 0;
-}
-
diff --git a/tools/xenstore/xs_random.c b/tools/xenstore/xs_random.c
deleted file mode 100644
index fdd723bb2a..0000000000
--- a/tools/xenstore/xs_random.c
+++ /dev/null
@@ -1,1590 +0,0 @@
-/* Random tests.
-
- We check that the results from a real filesystem are the same.
-*/
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <dirent.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <sys/wait.h>
-#include "xs.h"
-#include "talloc.h"
-#include "utils.h"
-
-struct ops
-{
- char *name;
-
- char **(*dir)(void *h, const char *path, unsigned int *num);
-
- void *(*read)(void *h, const char *path, unsigned int *len);
-
- bool (*write)(void *h, const char *path, const void *data,
- unsigned int len);
-
- bool (*mkdir)(void *h, const char *path);
-
- bool (*rm)(void *h, const char *path);
-
- struct xs_permissions *(*get_perms)(void *h,
- const char *path,
- unsigned int *num);
-
- bool (*set_perms)(void *h,
- const char *path,
- struct xs_permissions *perms,
- unsigned int num);
-
- bool (*transaction_start)(void *h);
- bool (*transaction_end)(void *h, bool abort);
-
- /* Create and destroy a new handle. */
- void *(*handle)(const char *path);
- void (*close)(void *);
-};
-
-struct file_ops_info
-{
- const char *base;
- char *transact_base;
-};
-
-static void convert_to_dir(const char *dirname)
-{
- char *tmpname = talloc_asprintf(dirname, "%s.tmp", dirname);
- if (rename(dirname, tmpname) != 0)
- barf_perror("Failed to rename %s to %s", dirname, tmpname);
- if (mkdir(dirname, 0700) != 0)
- barf_perror("Failed to mkdir %s", dirname);
- if (rename(tmpname,talloc_asprintf(dirname, "%s/.DATA", dirname)) != 0)
- barf_perror("Failed to rename into %s", dirname);
- /* If perms exists, move it in. */
- rename(talloc_asprintf(dirname, "%s.perms", dirname),
- talloc_asprintf(dirname, "%s/.perms", dirname));
-}
-
-/* Files can be used as dirs, too. Convert them when they are. */
-static void maybe_convert_to_directory(const char *filename)
-{
- struct stat st;
- char *dirname = talloc_asprintf(
- filename, "%.*s",
- (int)(strrchr(filename, '/') - filename), filename);
- if (lstat(dirname, &st) == 0 && S_ISREG(st.st_mode))
- convert_to_dir(dirname);
-}
-
-static char *get_name(struct file_ops_info *info, const char *path)
-{
- if (info->transact_base)
- return talloc_asprintf(path, "%s%s", info->transact_base,
- path);
- return talloc_asprintf(path, "%s%s", info->base, path);
-}
-
-static char *path_to_name(struct file_ops_info *info, const char *path)
-{
- char *filename = get_name(info, path);
- maybe_convert_to_directory(filename);
- return filename;
-}
-
-static char **file_directory(struct file_ops_info *info,
- const char *path, unsigned int *num)
-{
- char **ret;
- DIR *dir;
- struct dirent *dirent;
- char *p, *dirname = path_to_name(info, path);
- unsigned int i, len = 0;
- struct stat st;
-
- /* If it exists, but isn't a directory, we convert it. */
- if (lstat(dirname, &st) == 0 && !S_ISDIR(st.st_mode))
- convert_to_dir(dirname);
-
- *num = 0;
- dir = opendir(dirname);
- if (!dir)
- return NULL;;
-
- /* Once to count them. */
- while ((dirent = readdir(dir)) != NULL) {
- if (strchr(dirent->d_name, '.'))
- continue;
- len += strlen(dirent->d_name) + 1;
- (*num)++;
- }
- rewinddir(dir);
-
- /* Now allocate and fill in. */
- ret = malloc(sizeof(char *) * *num + len);
- p = (char *)&ret[*num];
- i = 0;
- while ((dirent = readdir(dir)) != NULL) {
- if (strchr(dirent->d_name, '.'))
- continue;
- ret[i] = p;
- strcpy(p, dirent->d_name);
- p += strlen(p) + 1;
- i++;
- }
- closedir(dir);
-
- return ret;
-}
-
-static char *filename_to_data(const char *filename)
-{
- struct stat st;
-
- if (lstat(filename, &st) == 0 && S_ISDIR(st.st_mode))
- return talloc_asprintf(filename, "%s/.DATA", filename);
- return (char *)filename;
-}
-
-static void *file_read(struct file_ops_info *info,
- const char *path, unsigned int *len)
-{
- void *ret;
- char *filename = filename_to_data(path_to_name(info, path));
- unsigned long size;
-
- ret = grab_file(filename, &size);
- /* Directory exists, .DATA doesn't. */
- if (!ret && errno == ENOENT && strends(filename, ".DATA")) {
- ret = strdup("");
- size = 0;
- }
- *len = size;
- return ret;
-}
-
-static struct xs_permissions *file_get_perms(struct file_ops_info *info,
- const char *path,
- unsigned int *num)
-{
- void *perms;
- struct xs_permissions *ret;
- char *filename = path_to_name(info, path);
- char *permfile;
- unsigned long size;
- struct stat st;
-
- if (lstat(filename, &st) != 0)
- return NULL;
-
- if (S_ISDIR(st.st_mode))
- permfile = talloc_asprintf(path, "%s/.perms", filename);
- else
- permfile = talloc_asprintf(path, "%s.perms", filename);
-
- perms = grab_file(permfile, &size);
- if (!perms)
- barf("Grabbing permissions for %s", permfile);
- *num = xs_count_strings(perms, size);
-
- ret = new_array(struct xs_permissions, *num);
- if (!xs_strings_to_perms(ret, *num, perms))
- barf("Reading permissions from %s", permfile);
- release_file(perms, size);
- return ret;
-}
-
-static void do_command(const char *cmd)
-{
- int ret;
-
- ret = system(cmd);
- if (ret == -1 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0)
- barf_perror("Failed '%s': %i", cmd, ret);
-}
-
-static void init_perms(const char *filename)
-{
- struct stat st;
- char *permfile, *command;
-
- if (lstat(filename, &st) != 0)
- barf_perror("Failed to stat %s", filename);
-
- if (S_ISDIR(st.st_mode))
- permfile = talloc_asprintf(filename, "%s/.perms", filename);
- else
- permfile = talloc_asprintf(filename, "%s.perms", filename);
-
- /* Leave permfile if it already exists. */
- if (lstat(permfile, &st) == 0)
- return;
-
- /* Copy permissions from parent */
- command = talloc_asprintf(filename, "cp %.*s/.perms %s",
- (int)(strrchr(filename, '/') - filename),
- filename, permfile);
- do_command(command);
-}
-
-static bool file_set_perms(struct file_ops_info *info,
- const char *path,
- struct xs_permissions *perms,
- unsigned int num)
-{
- unsigned int i;
- char *filename = path_to_name(info, path);
- char *permfile;
- int fd;
- struct stat st;
-
- if (num < 1) {
- errno = EINVAL;
- return false;
- }
-
- /* Check non-perm file exists/ */
- if (lstat(filename, &st) != 0)
- return false;
-
- if (S_ISDIR(st.st_mode))
- permfile = talloc_asprintf(path, "%s/.perms", filename);
- else
- permfile = talloc_asprintf(path, "%s.perms", filename);
-
- fd = open(permfile, O_WRONLY|O_CREAT|O_TRUNC, 0600);
- if (fd < 0)
- return false;
-
- for (i = 0; i < num; i++) {
- char buffer[100];
-
- if (!xs_perm_to_string(&perms[i], buffer)) {
- int saved_errno = errno;
- close(fd);
- errno = saved_errno;
- return false;
- }
- if (write(fd, buffer, strlen(buffer) + 1)
- != (int)strlen(buffer) + 1)
- barf_perror("Failed to write perm");
- }
- close(fd);
- return true;
-}
-
-static char *parent_filename(const char *name)
-{
- char *slash = strrchr(name + 1, '/');
- if (!slash)
- return talloc_strdup(name, "/");
- return talloc_asprintf(name, "%.*s", (int)(slash-name), name);
-}
-
-static void make_dirs(const char *filename)
-{
- struct stat st;
-
- if (lstat(filename, &st) == 0 && S_ISREG(st.st_mode))
- convert_to_dir(filename);
-
- if (mkdir(filename, 0700) == 0) {
- init_perms(filename);
- return;
- }
- if (errno == EEXIST)
- return;
-
- make_dirs(parent_filename(filename));
- if (mkdir(filename, 0700) != 0)
- barf_perror("Failed to mkdir %s", filename);
- init_perms(filename);
-}
-
-static bool file_write(struct file_ops_info *info,
- const char *path, const void *data,
- unsigned int len)
-{
- char *filename = filename_to_data(path_to_name(info, path));
- int fd;
-
- make_dirs(parent_filename(filename));
- fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0600);
- if (fd < 0)
- return false;
-
- if (write(fd, data, len) != (int)len)
- barf_perror("Bad write to %s", filename);
-
- init_perms(filename);
- close(fd);
- return true;
-}
-
-static bool file_mkdir(struct file_ops_info *info, const char *path)
-{
- char *dirname = path_to_name(info, path);
-
- make_dirs(parent_filename(dirname));
- if (mkdir(dirname, 0700) != 0)
- return (errno == EEXIST);
-
- init_perms(dirname);
- return true;
-}
-
-static bool file_rm(struct file_ops_info *info, const char *path)
-{
- char *filename = path_to_name(info, path);
- struct stat st;
-
- if (lstat(filename, &st) != 0) {
- if (lstat(parent_filename(filename), &st) != 0)
- return false;
- return true;
- }
-
- if (streq(path, "/")) {
- errno = EINVAL;
- return false;
- }
-
- do_command(talloc_asprintf(path, "rm -f %s.perms; rm -r %s",
- filename, filename));
- return true;
-}
-
-static bool file_transaction_start(struct file_ops_info *info)
-{
- char *cmd;
-
- if (info->transact_base) {
- errno = EBUSY;
- return false;
- }
-
- info->transact_base = talloc_asprintf(NULL, "%s.transact", info->base);
- cmd = talloc_asprintf(NULL, "cp -r %s %s",
- info->base, info->transact_base);
- do_command(cmd);
- talloc_free(cmd);
- return true;
-}
-
-static bool file_transaction_end(struct file_ops_info *info, bool abort)
-{
- char *old, *cmd;
-
- if (!info->transact_base) {
- errno = ENOENT;
- return false;
- }
-
- if (abort) {
- cmd = talloc_asprintf(NULL, "rm -rf %s", info->transact_base);
- do_command(cmd);
- goto success;
- }
-
- old = talloc_asprintf(NULL, "rm -rf %s", info->base);
- do_command(old);
- talloc_free(old);
-
- cmd = talloc_asprintf(NULL, "mv %s %s",
- info->transact_base, info->base);
- do_command(cmd);
-
-success:
- talloc_free(cmd);
- talloc_free(info->transact_base);
- info->transact_base = NULL;
- return true;
-}
-
-static struct file_ops_info *file_handle(const char *dir)
-{
- struct file_ops_info *info = talloc(NULL, struct file_ops_info);
-
- info->base = dir;
- info->transact_base = NULL;
- return info;
-}
-
-static void file_close(struct file_ops_info *handle)
-{
- talloc_free(handle);
-}
-
-static struct xs_handle *xs_handle(const char *dir __attribute__((unused)))
-{
- struct xs_handle *h;
-
- h = xs_daemon_open();
- if (!h)
- barf_perror("Connecting to xs daemon");
- return h;
-}
-
-static void xs_close(struct xs_handle *handle)
-{
- xs_daemon_close(handle);
-}
-
-struct ops file_ops = {
- .name = "FILE",
- .dir = (void *)file_directory,
- .read = (void *)file_read,
- .write = (void *)file_write,
- .mkdir = (void *)file_mkdir,
- .rm = (void *)file_rm,
- .get_perms = (void *)file_get_perms,
- .set_perms = (void *)file_set_perms,
- .transaction_start = (void *)file_transaction_start,
- .transaction_end = (void *)file_transaction_end,
- .handle = (void *)file_handle,
- .close = (void *)file_close,
-};
-
-struct ops xs_ops = {
- .name = "XS",
- .dir = (void *)xs_directory,
- .read = (void *)xs_read,
- .write = (void *)xs_write,
- .mkdir = (void *)xs_mkdir,
- .rm = (void *)xs_rm,
- .get_perms = (void *)xs_get_permissions,
- .set_perms = (void *)xs_set_permissions,
- .transaction_start = (void *)xs_transaction_start,
- .transaction_end = (void *)xs_transaction_end,
- .handle = (void *)xs_handle,
- .close = (void *)xs_close,
-};
-
-static int strptrcmp(const void *a, const void *b)
-{
- return strcmp(*(char **)a, *(char **)b);
-}
-
-static void sort_dir(char **dir, unsigned int num)
-{
- qsort(dir, num, sizeof(char *), strptrcmp);
-}
-
-static char *dump_dir(struct ops *ops,
- void *h,
- const char *node,
- char **dir,
- unsigned int numdirs,
- unsigned int depth)
-{
- char *ret = talloc_strdup(node, "");
- unsigned int i;
- char spacing[depth+1];
-
- memset(spacing, ' ', depth);
- spacing[depth] = '\0';
-
- sort_dir(dir, numdirs);
-
- for (i = 0; i < numdirs; i++) {
- struct xs_permissions *perms;
- unsigned int j, numperms;
- unsigned int len;
- char *contents;
- unsigned int subnum;
- char **subdirs;
- char *subret;
- char *subnode = talloc_asprintf(node, "%s/%s", node, dir[i]);
-
- perms = ops->get_perms(h, subnode, &numperms);
- if (!perms)
- return NULL;
- ret = talloc_asprintf_append(ret, "%s%s: ", spacing, dir[i]);
- for (j = 0; j < numperms; j++) {
- char buffer[100];
- if (!xs_perm_to_string(&perms[j], buffer))
- barf("perm to string");
- ret = talloc_asprintf_append(ret, "%s ", buffer);
- }
- free(perms);
- ret = talloc_asprintf_append(ret, "\n");
-
- /* Even directories can have contents. */
- contents = ops->read(h, subnode, &len);
- if (!contents) {
- if (errno != EISDIR)
- return NULL;
- } else {
- ret = talloc_asprintf_append(ret, " %s(%.*s)\n",
- spacing, len, contents);
- free(contents);
- }
-
- /* Every node is a directory. */
- subdirs = ops->dir(h, subnode, &subnum);
- if (!subdirs)
- return NULL;
- subret = dump_dir(ops, h, subnode, subdirs, subnum, depth+1);
- if (!subret)
- return NULL;
- ret = talloc_asprintf_append(ret, "%s", subret);
- free(subdirs);
- }
- return ret;
-}
-
-static char *dump(struct ops *ops, void *h)
-{
- char **subdirs;
- unsigned int subnum;
- char *ret = NULL, *root = talloc_strdup(NULL, "/");
-
- subdirs = ops->dir(h, root, &subnum);
- if (subdirs) {
- ret = dump_dir(ops, h, talloc_strdup(root, ""), subdirs,
- subnum, 0);
- free(subdirs);
- if (ret)
- talloc_steal(NULL, ret);
- }
- talloc_free(root);
- return ret;
-}
-
-/* jhash.h: Jenkins hash support.
- *
- * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
- *
- * http://burtleburtle.net/bob/hash/
- *
- * These are the credits from Bob's sources:
- *
- * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
- * hash(), hash2(), hash3, and mix() are externally useful functions.
- * Routines to test the hash are included if SELF_TEST is defined.
- * You can use this free for any purpose. It has no warranty.
- *
- * Copyright (C) 2003 David S. Miller (davem@redhat.com)
- *
- * I've modified Bob's hash to be useful in the Linux kernel, and
- * any bugs present are surely my fault. -DaveM
- */
-
-/* NOTE: Arguments are modified. */
-#define __jhash_mix(a, b, c) \
-{ \
- a -= b; a -= c; a ^= (c>>13); \
- b -= c; b -= a; b ^= (a<<8); \
- c -= a; c -= b; c ^= (b>>13); \
- a -= b; a -= c; a ^= (c>>12); \
- b -= c; b -= a; b ^= (a<<16); \
- c -= a; c -= b; c ^= (b>>5); \
- a -= b; a -= c; a ^= (c>>3); \
- b -= c; b -= a; b ^= (a<<10); \
- c -= a; c -= b; c ^= (b>>15); \
-}
-
-/* The golden ration: an arbitrary value */
-#define JHASH_GOLDEN_RATIO 0x9e3779b9
-
-/* The most generic version, hashes an arbitrary sequence
- * of bytes. No alignment or length assumptions are made about
- * the input key.
- */
-static inline uint32_t jhash(const void *key, uint32_t length, uint32_t initval)
-{
- uint32_t a, b, c, len;
- const uint8_t *k = key;
-
- len = length;
- a = b = JHASH_GOLDEN_RATIO;
- c = initval;
-
- while (len >= 12) {
- a += (k[0] +((uint32_t)k[1]<<8) +((uint32_t)k[2]<<16) +((uint32_t)k[3]<<24));
- b += (k[4] +((uint32_t)k[5]<<8) +((uint32_t)k[6]<<16) +((uint32_t)k[7]<<24));
- c += (k[8] +((uint32_t)k[9]<<8) +((uint32_t)k[10]<<16)+((uint32_t)k[11]<<24));
-
- __jhash_mix(a,b,c);
-
- k += 12;
- len -= 12;
- }
-
- c += length;
- switch (len) {
- case 11: c += ((uint32_t)k[10]<<24);
- case 10: c += ((uint32_t)k[9]<<16);
- case 9 : c += ((uint32_t)k[8]<<8);
- case 8 : b += ((uint32_t)k[7]<<24);
- case 7 : b += ((uint32_t)k[6]<<16);
- case 6 : b += ((uint32_t)k[5]<<8);
- case 5 : b += k[4];
- case 4 : a += ((uint32_t)k[3]<<24);
- case 3 : a += ((uint32_t)k[2]<<16);
- case 2 : a += ((uint32_t)k[1]<<8);
- case 1 : a += k[0];
- };
-
- __jhash_mix(a,b,c);
-
- return c;
-}
-
-/* A special optimized version that handles 1 or more of uint32_ts.
- * The length parameter here is the number of uint32_ts in the key.
- */
-static inline uint32_t jhash2(uint32_t *k, uint32_t length, uint32_t initval)
-{
- uint32_t a, b, c, len;
-
- a = b = JHASH_GOLDEN_RATIO;
- c = initval;
- len = length;
-
- while (len >= 3) {
- a += k[0];
- b += k[1];
- c += k[2];
- __jhash_mix(a, b, c);
- k += 3; len -= 3;
- }
-
- c += length * 4;
-
- switch (len) {
- case 2 : b += k[1];
- case 1 : a += k[0];
- };
-
- __jhash_mix(a,b,c);
-
- return c;
-}
-
-
-/* A special ultra-optimized versions that knows they are hashing exactly
- * 3, 2 or 1 word(s).
- *
- * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
- * done at the end is not done here.
- */
-static inline uint32_t jhash_3words(uint32_t a, uint32_t b, uint32_t c, uint32_t initval)
-{
- a += JHASH_GOLDEN_RATIO;
- b += JHASH_GOLDEN_RATIO;
- c += initval;
-
- __jhash_mix(a, b, c);
-
- return c;
-}
-
-static inline uint32_t jhash_2words(uint32_t a, uint32_t b, uint32_t initval)
-{
- return jhash_3words(a, b, 0, initval);
-}
-
-static inline uint32_t jhash_1word(uint32_t a, uint32_t initval)
-{
- return jhash_3words(a, 0, 0, initval);
-}
-
-static unsigned int get_randomness(int *state)
-{
- return jhash_1word((*state)++, *state * 1103515243);
-}
-
-static char *random_path(int *state)
-{
- unsigned int i;
- char *ret = NULL;
-
- if (get_randomness(state) % 20 == 0)
- return talloc_strdup(NULL, "/");
-
- for (i = 0; i < 1 || (get_randomness(state) % 2); i++) {
- ret = talloc_asprintf_append(ret, "/%i",
- get_randomness(state) % 15);
- }
- return ret;
-}
-
-static char *bool_to_errstring(bool result)
-{
- if (result)
- return talloc_strdup(NULL, "OK");
-
- /* Real daemon can never return this. */
- if (errno == ENOTDIR)
- errno = ENOENT;
- return talloc_asprintf(NULL, "FAILED:%s", strerror(errno));
-}
-
-static char *linearize_dir(char **dir, unsigned int *num)
-{
- char *result = NULL;
- unsigned int i;
-
- if (!dir)
- return bool_to_errstring(false);
-
- if (!*num) {
- free(dir);
- return talloc_strdup(NULL, "");
- }
-
- sort_dir(dir, *num);
- for (i = 0; i < *num; i++)
- result = talloc_asprintf_append(result, "%s\n", dir[i]);
- free(dir);
- return result;
-}
-
-static char *linearize_read(char *read, unsigned int *size)
-{
- char *ret;
-
- if (!read)
- return bool_to_errstring(false);
-
- ret = talloc_asprintf(NULL, "%i:%.*s", *size, *size, read);
- free(read);
- return ret;
-}
-
-static char *linearize_perms(struct xs_permissions *perms, unsigned int *size)
-{
- char *ret = NULL;
- unsigned int i;
-
- if (!perms)
- return bool_to_errstring(false);
-
- for (i = 0; i < *size; i++)
- ret = talloc_asprintf_append(ret, "(%u %u)",
- perms[i].id, perms[i].perms);
-
- free(perms);
- return ret;
-}
-
-/* Do the next operation, return the results. */
-static char *do_next_op(struct ops *ops, void *h, int state, bool verbose)
-{
- char *name;
- unsigned int num;
- char *ret;
-
- if (verbose)
- printf("State %i: ", state);
-
- name = random_path(&state);
- switch (get_randomness(&state) % 9) {
- case 0:
- if (verbose)
- printf("DIR %s\n", name);
- ret = linearize_dir(ops->dir(h, name, &num), &num);
- break;
- case 1:
- if (verbose)
- printf("READ %s\n", name);
- ret = linearize_read(ops->read(h, name, &num), &num);
- break;
- case 2: {
- char *contents = talloc_asprintf(NULL, "%i",
- get_randomness(&state));
- unsigned int len = get_randomness(&state)%(strlen(contents)+1);
- if (verbose)
- printf("WRITE %s %.*s\n", name, len, contents);
- ret = bool_to_errstring(ops->write(h, name, contents, len));
- talloc_steal(ret, contents);
- break;
- }
- case 3:
- if (verbose)
- printf("MKDIR %s\n", name);
- ret = bool_to_errstring(ops->mkdir(h, name));
- break;
- case 4:
- if (verbose)
- printf("RM %s\n", name);
- ret = bool_to_errstring(ops->rm(h, name));
- break;
- case 5:
- if (verbose)
- printf("GETPERMS %s\n", name);
- ret = linearize_perms(ops->get_perms(h, name, &num),
- &num);
- break;
- case 6: {
- unsigned int i, num = get_randomness(&state)%8;
- struct xs_permissions perms[num];
-
- if (verbose)
- printf("SETPERMS %s: ", name);
- for (i = 0; i < num; i++) {
- perms[i].id = get_randomness(&state)%8;
- perms[i].perms = get_randomness(&state)%4;
- if (verbose)
- printf("%i%c ", perms[i].id,
- perms[i].perms == XS_PERM_WRITE ? 'W'
- : perms[i].perms == XS_PERM_READ ? 'R'
- : perms[i].perms ==
- (XS_PERM_READ|XS_PERM_WRITE) ? 'B'
- : 'N');
- }
- if (verbose)
- printf("\n");
- ret = bool_to_errstring(ops->set_perms(h, name, perms,
- num));
- break;
- }
- case 7: {
- if (verbose)
- printf("START %s\n", name);
- ret = bool_to_errstring(ops->transaction_start(h));
- if (streq(ret, "OK")) {
- talloc_free(ret);
- ret = talloc_asprintf(NULL, "OK:START-TRANSACT");
- }
-
- break;
- }
- case 8: {
- bool abort = (get_randomness(&state) % 2);
-
- if (verbose)
- printf("STOP %s\n", abort ? "ABORT" : "COMMIT");
- ret = bool_to_errstring(ops->transaction_end(h, abort));
- if (streq(ret, "OK")) {
- talloc_free(ret);
- ret = talloc_strdup(NULL, "OK:STOP-TRANSACT");
- }
- break;
- }
- default:
- barf("Impossible randomness");
- }
-
- talloc_steal(ret, name);
- return ret;
-}
-
-static int daemon_pid;
-
-static void cleanup_xs_ops(void)
-{
- char *cmd;
-
- if (daemon_pid) {
- kill(daemon_pid, SIGTERM);
- waitpid(daemon_pid, NULL, 0);
- daemon_pid = 0;
- }
-
- cmd = talloc_asprintf(NULL, "rm -rf testsuite/tmp/*");
- do_command(cmd);
- talloc_free(cmd);
-}
-
-static void cleanup_file_ops(const char *dir)
-{
- char *cmd;
-
- cmd = talloc_asprintf(NULL, "rm -rf %s %s.transact", dir, dir);
- do_command(cmd);
- talloc_free(cmd);
-}
-
-static void cleanup(const char *dir)
-{
- cleanup_xs_ops();
- cleanup_file_ops(dir);
-}
-
-static void setup_file_ops(const char *dir)
-{
- struct xs_permissions perm = { .id = 0, .perms = XS_PERM_READ };
- struct file_ops_info *h = file_handle(dir);
- if (mkdir(dir, 0700) != 0)
- barf_perror("Creating directory %s", dir);
- if (mkdir(talloc_asprintf(h, "%s/tool", dir), 0700) != 0)
- barf_perror("Creating directory %s/tool", dir);
- if (!file_set_perms(h, talloc_strdup(h, "/"), &perm, 1))
- barf_perror("Setting root perms in %s", dir);
- if (!file_set_perms(h, talloc_strdup(h, "/tool"), &perm, 1))
- barf_perror("Setting root perms in %s/tool", dir);
- file_close(h);
-}
-
-static void setup_xs_ops(void)
-{
- int fds[2];
-
- /* Start daemon. */
- pipe(fds);
- if ((daemon_pid = fork())) {
- /* Child writes PID when its ready: we wait for that. */
- char buffer[20];
- close(fds[1]);
- if (read(fds[0], buffer, sizeof(buffer)) < 0)
- barf("Failed to summon daemon");
- close(fds[0]);
- } else {
- dup2(fds[1], STDOUT_FILENO);
- close(fds[0]);
-#if 1
- execlp("valgrind", "valgrind", "-q", "--suppressions=testsuite/vg-suppressions", "xenstored_test", "--output-pid",
- "--no-fork", NULL);
-#else
- execlp("./xenstored_test", "xenstored_test", "--output-pid",
- "--no-fork", NULL);
-#endif
- exit(1);
- }
-}
-
-static void setup(const char *dir)
-{
- setup_file_ops(dir);
- setup_xs_ops();
-};
-
-struct simple_data
-{
- unsigned int seed;
- bool print_progress;
- bool fast;
- struct ops *ops;
- const char *dir;
-};
-
-/* Just a random test. Don't care about results, just that it doesn't
- * go boom. */
-static unsigned int try_simple(const bool *trymap,
- unsigned int number,
- bool verbose,
- void *_data)
-{
- unsigned int i, print;
- void *h;
- char *snapshot = NULL;
- struct simple_data *data = _data;
-
- if (data->ops == &xs_ops) {
- cleanup_xs_ops();
- setup_xs_ops();
- } else {
- cleanup_file_ops(data->dir);
- setup_file_ops(data->dir);
- }
- h = data->ops->handle(data->dir);
-
- print = number / 76;
- if (!print)
- print = 1;
-
- for (i = 0; i < number; i++) {
- char *ret;
-
- if (data->print_progress) {
- if (i % print == 0) {
- printf(".");
- fflush(stdout);
- }
- }
-
- if (trymap && !trymap[i])
- continue;
-
- ret = do_next_op(data->ops, h, i + data->seed, verbose);
- if (verbose)
- printf("-> %.*s\n",
- (int)(strchr(ret, '\n') - ret), ret);
- if (streq(ret, "FAILED:Bad file descriptor"))
- goto out;
- if (kill(daemon_pid, 0) != 0)
- goto out;
-
- if (!data->fast) {
- if (streq(ret, "OK:START-TRANSACT")) {
- void *pre = data->ops->handle(data->dir);
-
- snapshot = dump(data->ops, pre);
- if (!snapshot)
- goto out;
- data->ops->close(pre);
- } else if (streq(ret, "OK:STOP-TRANSACT")) {
- talloc_free(snapshot);
- snapshot = NULL;
- }
- }
-
- talloc_free(ret);
-
- if (snapshot) {
- void *pre = data->ops->handle(data->dir);
- char *contents;
-
- contents = dump(data->ops, pre);
- if (!contents)
- goto out;
-
- if (!streq(contents, snapshot))
- goto out;
-
- talloc_free(contents);
- data->ops->close(pre);
- }
- }
-out:
- data->ops->close(h);
- return i;
-}
-
-/* Binary elimination: try eliminating all of them, then reduce. */
-static void reduce(bool *map,
- unsigned int number,
- unsigned int try_start, unsigned int try_num,
- unsigned int (*try)(const bool *map,
- unsigned int number,
- bool verbose,
- void *),
- void *data)
-{
- bool newmap[number];
-
- if (try_num == 0)
- return;
-
- /* Try skipping everything between start and end. */
- memcpy(newmap, map, sizeof(newmap));
- memset(newmap + try_start, 0, try_num * sizeof(bool));
-
- /* We want the *same* failure: must fail at "number-1". */
- if (try(newmap, number, false, data) == number - 1) {
- memset(map + try_start, 0, try_num * sizeof(bool));
- return;
- }
-
- if (try_num == 1)
- return;
-
- /* Try each half... */
- reduce(map, number, try_start, try_num/2, try, data);
- reduce(map, number, try_start + try_num/2, try_num - try_num/2,
- try, data);
-}
-
-static void reduce_problem(unsigned int failed,
- unsigned int (*try)(const bool *map,
- unsigned int number,
- bool verbose,
- void *data),
- void *data)
-{
- bool map[failed];
-
- memset(map, 1, sizeof(map));
- reduce(map, failed, 0, failed-1, try, data);
-
- printf("Cut down:\n");
- if (try(map, failed, true, data) != failed - 1) {
- printf("Except, that didn't actually fail. Bugger!");
- exit(2);
- }
- exit(1);
-}
-
-/* Just a random test. Don't care about results, just that it doesn't
- * go boom. */
-static void simple_test(const char *dir,
- unsigned int iters, unsigned int seed,
- bool fast, bool verbose)
-{
- struct simple_data data;
- unsigned int try;
-
- data.seed = seed;
- data.print_progress = !verbose;
- data.fast = fast;
- data.ops = &xs_ops;
- data.dir = dir;
-
- try = try_simple(NULL, iters, verbose, &data);
- if (try == iters) {
- cleanup_xs_ops();
- exit(0);
- }
- printf("Failed on iteration %u of seed %u\n", try + 1, seed);
- data.print_progress = false;
- reduce_problem(try + 1, try_simple, &data);
-}
-
-static bool ops_equal(struct ops *a, void *ah,
- struct ops *b, void *bh,
- const char *node,
- struct ops **fail)
-{
- char **dira = NULL, **dirb = NULL;
- char *dataa = NULL, *datab = NULL;
- unsigned int i, numa, numb, lena, lenb;
- struct xs_permissions *permsa = NULL, *permsb = NULL;
- unsigned int numpermsa, numpermsb;
- char *nodename;
- bool ret = false;
-
- /* Ignore tool/ dir. */
- if (streq(node, "/tool"))
- return true;
-
- /* FILE backend expects talloc'ed pointer. */
- nodename = talloc_strdup(NULL, node);
- permsa = a->get_perms(ah, nodename, &numpermsa);
- if (!permsa) {
- *fail = a;
- goto out;
- }
- permsb = b->get_perms(bh, nodename, &numpermsb);
- if (!permsb) {
- *fail = b;
- goto out;
- }
- if (numpermsa != numpermsb)
- goto out;
- for (i = 0; i < numpermsa; i++) {
- if (permsa[i].perms != permsb[i].perms)
- goto out;
- if (permsa[i].id != permsb[i].id)
- goto out;
- }
-
- /* Non-pure-directory nodes contain data. */
- dataa = a->read(ah, nodename, &lena);
- if (!dataa && errno != EISDIR) {
- *fail = a;
- goto out;
- }
- datab = b->read(bh, nodename, &lenb);
- if (!datab && errno != EISDIR) {
- *fail = b;
- goto out;
- }
-
- if (dataa) {
- if (!datab)
- goto out;
- if (lena != lenb)
- goto out;
-
- if (memcmp(dataa, datab, lena) != 0)
- goto out;
- } else
- if (datab)
- goto out;
-
- /* Everything is a directory. */
- dira = a->dir(ah, nodename, &numa);
- if (!dira) {
- *fail = a;
- goto out;
- }
- dirb = b->dir(bh, nodename, &numb);
- if (!dirb) {
- *fail = b;
- goto out;
- }
- if (numa != numb)
- goto out;
- sort_dir(dira, numa);
- sort_dir(dirb, numb);
- for (i = 0; i < numa; i++) {
- char subnode[strlen(node) + 1 + strlen(dira[i]) + 1];
-
- if (!streq(dira[i], dirb[i]))
- goto out;
-
- strcpy(subnode, node);
- if (!streq(node, "/"))
- strcat(subnode, "/");
- strcat(subnode, dira[i]);
- if (!ops_equal(a, ah, b, bh, subnode, fail))
- goto out;
- }
-
- ret = true;
-out:
- free(permsa);
- free(permsb);
- free(dataa);
- free(datab);
- free(dira);
- free(dirb);
- talloc_free(nodename);
- return ret;
-}
-
-struct diff_data
-{
- unsigned int seed;
- bool print_progress;
- bool fast;
- const char *dir;
-};
-
-/* Differential: try both file and xs backend, watch for differences. */
-static unsigned int try_diff(const bool *trymap,
- unsigned int number,
- bool verbose,
- void *_data)
-{
- void *fileh, *xsh;
- bool transact = false;
- struct ops *fail;
- struct diff_data *data = _data;
- unsigned int i, print;
-
- cleanup(data->dir);
- setup(data->dir);
-
- fileh = file_handle(data->dir);
- xsh = xs_handle(data->dir);
-
- print = number / 76;
- if (!print)
- print = 1;
-
- for (i = 0; i < number; i++) {
- char *file, *xs;
-
- if (data->print_progress) {
- if (i % print == 0) {
- printf(".");
- fflush(stdout);
- }
- }
- if (trymap && !trymap[i])
- continue;
-
- if (verbose)
- printf("FILE: ");
-
- file = do_next_op(&file_ops, fileh, i+data->seed, verbose);
- if (verbose)
- printf("-> %.*s\n",
- (int)(strchr(file, '/') - file), file);
-
- if (verbose)
- printf("XS: ");
- xs = do_next_op(&xs_ops, xsh, i+data->seed, verbose);
- if (verbose)
- printf("-> %.*s\n", (int)(strchr(xs, '/') - xs), xs);
-
- if (!streq(file, xs))
- goto out;
-
- if (strstarts(file, "OK:START-TRANSACT:"))
- transact = true;
- else if (streq(file, "OK:STOP-TRANSACT"))
- transact = false;
-
- talloc_free(file);
- talloc_free(xs);
-
- if (data->fast)
- continue;
-
- fail = NULL;
- if (!ops_equal(&xs_ops, xsh, &file_ops, fileh, "/", &fail)) {
- if (fail)
- barf("%s failed during test\n", fail->name);
- if (verbose)
- printf("Trees differ:\nXS:%s\nFILE%s\n",
- dump(&xs_ops, xsh),
- dump(&file_ops, fileh));
- goto out;
- }
-
- if (transact) {
- void *fileh_pre = file_handle(data->dir);
- void *xsh_pre = xs_handle(data->dir);
-
- fail = NULL;
- if (!ops_equal(&xs_ops, xsh_pre, &file_ops, fileh_pre,
- "/", &fail)) {
- if (fail)
- barf("%s failed during transact\n",
- fail->name);
-
- xs_daemon_close(xsh_pre);
- talloc_free(fileh_pre);
- goto out;
- }
- xs_daemon_close(xsh_pre);
- talloc_free(fileh_pre);
- }
- }
-
- fail = NULL;
- if (data->fast)
- if (!ops_equal(&xs_ops, xsh, &file_ops, fileh, "/", &fail))
- barf("Final result not the same: try without --fast");
-out:
- file_ops.close(fileh);
- xs_ops.close(xsh);
- return i;
-}
-
-/* Differential random test: compare results against file backend. */
-static void diff_test(const char *dir,
- unsigned int iters, unsigned int seed, bool fast,
- bool verbose)
-{
- struct diff_data data;
- unsigned int try;
-
- data.seed = seed;
- data.print_progress = !verbose;
- data.fast = fast;
- data.dir = dir;
-
- try = try_diff(NULL, iters, verbose, &data);
- if (try == iters) {
- cleanup_xs_ops();
- exit(0);
- }
- printf("Failed on iteration %u of seed %u\n", try + 1, seed);
- data.print_progress = false;
- reduce_problem(try + 1, try_diff, &data);
-}
-
-struct fail_data
-{
- unsigned int seed;
- bool print_progress;
- const char *dir;
-};
-
-/* Try xs with inserted failures: every op should either succeed or fail. */
-static unsigned int try_fail(const bool *trymap,
- unsigned int number,
- bool verbose,
- void *_data)
-{
- unsigned int i, print, tried = 0, aborted = 0;
- struct fail_data *data = _data;
- struct xs_handle *tmpxsh;
- struct file_ops_info *tmpfileh;
- void *fileh, *xsh;
- struct ops *fail;
- char seed[20];
-
- /* Make sure failures off to shut down. */
- if (daemon_pid)
- kill(daemon_pid, SIGUSR1);
- cleanup(data->dir);
- setup(data->dir);
-
- fileh = file_handle(data->dir);
- xsh = xs_handle(data->dir);
-
- print = number / 76;
- if (!print)
- print = 1;
-
- for (i = 0; i < number; i++) {
- unsigned int limit, failed;
- char *ret;
-
- /* A few times we fail due to other end OOM. */
- limit = 0;
- while (!xsh) {
- xsh = xs_handle(data->dir);
- if (!xsh && errno == ECONNREFUSED) {
- if (verbose)
- printf("Daemon refused connection\n");
- goto out;
- }
- if (!xsh && limit++ == 5) {
- printf("Daemon failed conn 5 times\n");
- goto out;
- }
- }
-
- if (data->print_progress) {
- if (i % print == 0) {
- printf(".");
- fflush(stdout);
- }
- }
- if (trymap && !trymap[i])
- continue;
-
- /* Turn on failure. */
- sprintf(seed, "%i", data->seed + i);
- free(xs_debug_command(xsh, "failtest",seed,strlen(seed)+1));
-
- if (verbose)
- printf("(%i) seed %s ", i, seed);
- ret = do_next_op(&xs_ops, xsh, i + data->seed, verbose);
- if (streq(ret, "FAILED:Connection reset by peer")
- || streq(ret, "FAILED:Bad file descriptor")
- || streq(ret, "FAILED:Broken pipe")) {
- xs_close(xsh);
- xsh = NULL;
- failed = 2;
- } else if (strstarts(ret, "OK"))
- failed = 0;
- else
- failed = 1;
-
- tried++;
- if (xsh)
- aborted++;
-
- if (verbose)
- printf("-> %.*s\n",
- (int)(strchr(ret, '\n') - ret), ret);
-
- talloc_free(ret);
-
- /* Turn off failures using signal. */
- if (kill(daemon_pid, SIGUSR1) != 0) {
- if (verbose)
- printf("Failed to signal daemon\n");
- goto out;
- }
-
- if (failed == 0) {
- /* Succeeded? Do same thing to file backend
- * to compare */
- try_applying:
- ret = do_next_op(&file_ops, fileh, i + data->seed,
- false);
- if (!strstarts(ret, "OK")) {
- if (!verbose)
- printf("File op failed on %i\n",
- i + data->seed);
- talloc_free(ret);
- goto out;
- }
- talloc_free(ret);
- }
-
- tmpxsh = xs_handle(data->dir);
- if (!tmpxsh) {
- if (verbose)
- printf("Failed to open signalled daemon");
- goto out;
- }
- tmpfileh = file_handle(data->dir);
-
- fail = NULL;
- if (!ops_equal(&xs_ops, tmpxsh, &file_ops, tmpfileh, "/",
- &fail)) {
- if (fail) {
- if (verbose)
- printf("%s failed\n", fail->name);
- goto out;
- }
- /* Maybe op succeeded: try comparing after local op? */
- if (failed == 2) {
- failed = 0;
- if (verbose)
- printf("(Looks like it succeeded)\n");
- xs_close(tmpxsh);
- file_close(tmpfileh);
- goto try_applying;
- }
- if (verbose)
- printf("Trees differ:\nXS:%s\nFILE:%s\n",
- dump(&xs_ops, tmpxsh),
- dump(&file_ops, tmpfileh));
- xs_close(tmpxsh);
- file_close(tmpfileh);
- goto out;
- }
-
- /* If we lost the xs handle, that ended the transaction */
- if (!xsh)
- file_transaction_end(fileh, true);
-
- xs_close(tmpxsh);
- file_close(tmpfileh);
- }
-out:
- if (xsh)
- xs_close(xsh);
- return i;
-}
-
-static void fail_test(const char *dir,
- unsigned int iters, unsigned int seed,
- bool fast __attribute__((unused)), bool verbose)
-{
- struct fail_data data;
- unsigned int try;
-
- data.seed = seed;
- data.print_progress = !verbose;
- data.dir = dir;
-
- try = try_fail(NULL, iters, verbose, &data);
- if (try == iters) {
- cleanup_xs_ops();
- exit(0);
- }
- printf("Failed on iteration %u of seed %u\n", try + 1, seed);
- fflush(stdout);
- data.print_progress = false;
- reduce_problem(try + 1, try_fail, &data);
-}
-
-int main(int argc, char *argv[])
-{
- bool verbose = false;
- bool simple = false;
- bool fast = false;
- bool fail = false;
-
- if (argv[1] && streq(argv[1], "--fail")) {
- fail = true;
- argv++;
- argc--;
- }
-
- if (argv[1] && streq(argv[1], "--simple")) {
- simple = true;
- argv++;
- argc--;
- }
-
- if (argv[1] && streq(argv[1], "--fast")) {
- fast = true;
- argv++;
- argc--;
- }
-
- if (argv[1] && streq(argv[1], "--verbose")) {
- verbose = true;
- argv++;
- argc--;
- }
-
- if (argc != 4)
- barf("Usage: xs_random [--fail|--simple] [--fast] [--verbose] <directory> <iterations> <seed>");
-
- talloc_enable_null_tracking();
-
- if (fail)
- fail_test(argv[1], atoi(argv[2]), atoi(argv[3]), fast, verbose);
- else if (simple)
- simple_test(argv[1], atoi(argv[2]), atoi(argv[3]), fast, verbose);
- else
- diff_test(argv[1], atoi(argv[2]), atoi(argv[3]), fast, verbose);
- exit(2);
-}
diff --git a/tools/xenstore/xs_stress.c b/tools/xenstore/xs_stress.c
deleted file mode 100644
index d4f4ddf554..0000000000
--- a/tools/xenstore/xs_stress.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/* Stress test for Xen Store: multiple people hammering transactions */
-#include "xs.h"
-#include "utils.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-
-#define NUM_HANDLES 2
-#define DIR_FANOUT 3
-#define DIR_DEPTH 3
-
-/* How often to print progress */
-static int print;
-
-/* Layout looks like /<num>/<num>/count. */
-static void work(unsigned int cycles, unsigned int childnum)
-{
- unsigned int i;
- struct xs_handle *handles[NUM_HANDLES];
- char id;
-
- if (childnum < 10)
- id = '0' + childnum;
- else
- id = 'A' + childnum - 10;
-
- for (i = 0; i < NUM_HANDLES; i++) {
- handles[i] = xs_daemon_open();
- if (!handles[i])
- barf_perror("Opening handle %i", i);
- }
-
- srandom(childnum);
- for (i = 0; i < cycles; i++) {
- unsigned int j, len;
- char file[100] = "";
- char *contents, tmp[100];
- struct xs_handle *h = handles[random() % NUM_HANDLES];
-
- for (j = 0; j < DIR_DEPTH; j++)
- sprintf(file + strlen(file), "/%li",
- random()%DIR_FANOUT);
-
- if (!xs_transaction_start(h))
- barf_perror("%i: starting transaction %i",
- childnum, i);
-
- sprintf(file + strlen(file), "/count");
- contents = xs_read(h, file, &len);
- if (!contents)
- barf_perror("%i: can't read %s iter %i",
- childnum, file, i);
- sprintf(tmp, "%i", atoi(contents) + 1);
- if (!xs_write(h, file, tmp, strlen(tmp)+1))
- barf_perror("%i: can't write %s iter %i",
- childnum, file, i);
-
- /* Abandon 1 in 10 */
- if (random() % 10 == 0) {
- if (!xs_transaction_end(h, true))
- barf_perror("%i: can't abort transact",
- childnum);
- i--;
- } else {
- if (!xs_transaction_end(h, false)) {
- if (errno == EAGAIN) {
- write(STDOUT_FILENO, "!", 1);
- i--;
- } else
- barf_perror("%i: can't commit trans",
- childnum);
- } else {
- /* Offset when we print . so kids don't all
- * print at once. */
- if ((i + print/(childnum+1)) % print == 0)
- write(STDOUT_FILENO, &id, 1);
- }
- }
- }
-}
-
-static void create_dirs(struct xs_handle *h, const char *base, int togo)
-{
- unsigned int i;
- char filename[100];
-
- if (togo == 0) {
- sprintf(filename, "%s/count", base);
- if (!xs_write(h, filename, "0", 1))
- barf_perror("Writing to %s", filename);
- return;
- }
-
- for (i = 0; i < DIR_FANOUT; i++) {
- sprintf(filename, "%s/%i", base, i);
- if (!xs_mkdir(h, filename))
- barf_perror("xs_mkdir %s", filename);
- create_dirs(h, filename, togo-1);
- }
-}
-
-static unsigned int add_count(struct xs_handle *h, const char *base, int togo)
-{
- unsigned int i, count;
- char filename[100];
-
- if (togo == 0) {
- char *answer;
- unsigned int len;
-
- sprintf(filename, "%s/count", base);
- answer = xs_read(h, filename, &len);
- if (!answer)
- barf_perror("Reading %s", filename);
- count = atoi(answer);
- free(answer);
- return count;
- }
-
- count = 0;
- for (i = 0; i < DIR_FANOUT; i++) {
- sprintf(filename, "%s/%i", base, i);
- count += add_count(h, filename, togo-1);
- }
- return count;
-}
-
-static void setup(void)
-{
- struct xs_handle *h;
-
- /* Do setup. */
- h = xs_daemon_open();
- if (!h)
- barf_perror("Contacting daemon");
- create_dirs(h, "", DIR_DEPTH);
- xs_daemon_close(h);
-}
-
-static unsigned int tally_counts(void)
-{
- struct xs_handle *h;
- unsigned int ret;
-
- h = xs_daemon_open();
- if (!h)
- barf_perror("Contacting daemon");
-
- ret = add_count(h, "", DIR_DEPTH);
- xs_daemon_close(h);
- return ret;
-}
-
-int main(int argc, char *argv[])
-{
- unsigned int i;
- bool failed = false;
- int kids[10];
-
- if (argc != 2)
- barf("Usage: xs_stress <iterations>");
-
- printf("Setting up directories...\n");
- setup();
-
- print = atoi(argv[1]) / 76;
- if (!print)
- print = 1;
-
- printf("Running %i children...\n", ARRAY_SIZE(kids));
- for (i = 0; i < ARRAY_SIZE(kids); i++) {
- kids[i] = fork();
- if (kids[i] == -1)
- barf_perror("fork");
- if (kids[i] == 0) {
- work(atoi(argv[1]) / ARRAY_SIZE(kids), i);
- exit(0);
- }
- }
-
- for (i = 0; i < ARRAY_SIZE(kids); i++) {
- int status;
- if (waitpid(kids[i], &status, 0) == -1)
- barf_perror("waitpid");
- if (!WIFEXITED(status))
- barf("Kid %i died via signal %i\n",
- i, WTERMSIG(status));
- if (WEXITSTATUS(status) != 0) {
- printf("Child %i exited %i\n", i, WEXITSTATUS(status));
- failed = true;
- }
- }
- if (failed)
- exit(1);
-
- printf("\nCounting results...\n");
- i = tally_counts();
- if (i != (unsigned)atoi(argv[1]))
- barf("Total counts %i not %s", i, argv[1]);
- printf("Success!\n");
- exit(0);
-}
diff --git a/tools/xenstore/xs_test.c b/tools/xenstore/xs_test.c
deleted file mode 100644
index 8b1a5ebf1a..0000000000
--- a/tools/xenstore/xs_test.c
+++ /dev/null
@@ -1,812 +0,0 @@
-/*
- Xen Store Daemon Test tool
- Copyright (C) 2005 Rusty Russell IBM Corporation
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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 <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <sys/mman.h>
-#include <fnmatch.h>
-#include <stdarg.h>
-#include <string.h>
-#include <getopt.h>
-#include <ctype.h>
-#include <sys/time.h>
-#include "utils.h"
-#include "xs_lib.h"
-#include "xs.h"
-#include "list.h"
-
-#define XSTEST
-
-static struct xs_handle *handles[10] = { NULL };
-static xs_transaction_t txh[10] = { XBT_NULL };
-
-static unsigned int timeout_ms = 500;
-static bool timeout_suppressed = true;
-static bool readonly = false;
-static bool print_input = false;
-static unsigned int linenum = 0;
-
-static int daemon_pid;
-static struct xenstore_domain_interface *interface;
-
-/* FIXME: Mark connection as broken (close it?) when this happens. */
-static bool check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
-{
- return ((prod - cons) <= XENSTORE_RING_SIZE);
-}
-
-static void *get_output_chunk(XENSTORE_RING_IDX cons,
- XENSTORE_RING_IDX prod,
- char *buf, uint32_t *len)
-{
- *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod);
- if ((XENSTORE_RING_SIZE - (prod - cons)) < *len)
- *len = XENSTORE_RING_SIZE - (prod - cons);
- return buf + MASK_XENSTORE_IDX(prod);
-}
-
-static const void *get_input_chunk(XENSTORE_RING_IDX cons,
- XENSTORE_RING_IDX prod,
- const char *buf, uint32_t *len)
-{
- *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons);
- if ((prod - cons) < *len)
- *len = prod - cons;
- return buf + MASK_XENSTORE_IDX(cons);
-}
-
-/* FIXME: We spin, and we're sloppy. */
-static bool read_all_shmem(int fd __attribute__((unused)),
- void *data, unsigned int len)
-{
- unsigned int avail;
- struct xenstore_domain_interface *intf = interface;
- XENSTORE_RING_IDX cons, prod;
- const void *src;
-
- while (len) {
- cons = intf->rsp_cons;
- prod = intf->rsp_prod;
- if (!check_indexes(cons, prod))
- barf("Corrupt buffer");
-
- src = get_input_chunk(cons, prod, intf->rsp, &avail);
- if (avail > len)
- avail = len;
- memcpy(data, src, avail);
- data += avail;
- len -= avail;
- intf->rsp_cons += avail;
- }
-
- /* Tell other end we read something. */
- kill(daemon_pid, SIGUSR2);
-
- return true;
-}
-
-static bool write_all_shmem(int fd __attribute__((unused)),
- const void *data, unsigned int len)
-{
- uint32_t avail;
- struct xenstore_domain_interface *intf = interface;
- XENSTORE_RING_IDX cons, prod;
- void *dst;
-
- while (len) {
- cons = intf->req_cons;
- prod = intf->req_prod;
- if (!check_indexes(cons, prod))
- barf("Corrupt buffer");
-
- dst = get_output_chunk(cons, prod, intf->req, &avail);
- if (avail > len)
- avail = len;
- memcpy(dst, data, avail);
- data += avail;
- len -= avail;
- intf->req_prod += avail;
- }
-
- /* Tell other end we wrote something. */
- kill(daemon_pid, SIGUSR2);
-
- return true;
-}
-
-static bool read_all(int fd, void *data, unsigned int len);
-static bool read_all_choice(int fd, void *data, unsigned int len)
-{
- if (fd == -2)
- return read_all_shmem(fd, data, len);
- return read_all(fd, data, len);
-}
-
-static bool write_all_choice(int fd, const void *data, unsigned int len)
-{
- if (fd == -2)
- return write_all_shmem(fd, data, len);
- return xs_write_all(fd, data, len);
-}
-
-/* We want access to internal functions. */
-#include "xs.c"
-
-static void __attribute__((noreturn)) usage(void)
-{
- barf("Usage:\n"
- " xs_test [--readonly] [--no-timeout] [-x]\n"
- "Reads commands from stdin, one per line:"
- " dir <path>\n"
- " read <path>\n"
- " write <path> <value>...\n"
- " setid <id>\n"
- " mkdir <path>\n"
- " rm <path>\n"
- " getperm <path>\n"
- " setperm <path> <id> <flags> ...\n"
- " watch <path> <token>\n"
- " watchnoack <path> <token>\n"
- " waitwatch\n"
- " unwatch <path> <token>\n"
- " close\n"
- " start <node>\n"
- " abort\n"
- " introduce <domid> <mfn> <eventchn> <path>\n"
- " commit\n"
- " sleep <milliseconds>\n"
- " expect <pattern>\n"
- " notimeout\n"
- " readonly\n"
- " readwrite\n"
- " dump\n");
-}
-
-static int argpos(const char *line, unsigned int num)
-{
- unsigned int i, len = 0, off = 0;
-
- for (i = 0; i <= num; i++) {
- off += len;
- off += strspn(line + off, " \t\n");
- len = strcspn(line + off, " \t\n");
- if (!len)
- return off;
- }
- return off;
-}
-
-static char *arg(const char *line, unsigned int num)
-{
- static char *args[10];
- unsigned int off, len;
-
- off = argpos(line, num);
- len = strcspn(line + off, " \t\n");
-
- if (!len)
- barf("Can't get arg %u", num);
-
- free(args[num]);
- args[num] = malloc(len + 1);
- memcpy(args[num], line+off, len);
- args[num][len] = '\0';
- return args[num];
-}
-
-struct expect
-{
- struct list_head list;
- char *pattern;
-};
-static LIST_HEAD(expects);
-
-static char *command;
-
-/* Trim leading and trailing whitespace */
-static void trim(char *str)
-{
- while (isspace(str[0]))
- memmove(str, str+1, strlen(str));
-
- while (strlen(str) && isspace(str[strlen(str)-1]))
- str[strlen(str)-1] = '\0';
-}
-
-static void output(const char *fmt, ...)
-{
- char *str;
- struct expect *i;
- va_list arglist;
-
- va_start(arglist, fmt);
- vasprintf(&str, fmt, arglist);
- va_end(arglist);
-
- printf("%s", str);
- fflush(stdout);
- trim(str);
- list_for_each_entry(i, &expects, list) {
- if (fnmatch(i->pattern, str, 0) == 0) {
- list_del(&i->list);
- free(i);
- return;
- }
- }
- barf("Unexpected output %s\n", str);
-}
-
-static void failed(int handle)
-{
- if (handle)
- output("%i: %s failed: %s\n",
- handle, command, strerror(errno));
- else
- output("%s failed: %s\n", command, strerror(errno));
-}
-
-static void expect(const char *line)
-{
- struct expect *e = malloc(sizeof(*e));
-
- e->pattern = strdup(line + argpos(line, 1));
- trim(e->pattern);
- list_add(&e->list, &expects);
-}
-
-static void do_dir(unsigned int handle, char *path)
-{
- char **entries;
- unsigned int i, num;
-
- entries = xs_directory(handles[handle], txh[handle], path, &num);
- if (!entries) {
- failed(handle);
- return;
- }
-
- for (i = 0; i < num; i++)
- if (handle)
- output("%i:%s\n", handle, entries[i]);
- else
- output("%s\n", entries[i]);
- free(entries);
-}
-
-static void do_read(unsigned int handle, char *path)
-{
- char *value;
- unsigned int len;
-
- value = xs_read(handles[handle], txh[handle], path, &len);
- if (!value) {
- failed(handle);
- return;
- }
-
- /* It's supposed to nul terminate for us. */
- assert(value[len] == '\0');
- if (handle)
- output("%i:%.*s\n", handle, len, value);
- else
- output("%.*s\n", len, value);
-}
-
-static void do_write(unsigned int handle, char *path, char *data)
-{
- if (!xs_write(handles[handle], txh[handle], path, data, strlen(data)))
- failed(handle);
-}
-
-static void do_setid(unsigned int handle, char *id)
-{
- if (!xs_bool(xs_debug_command(handles[handle], "setid", id,
- strlen(id)+1)))
- failed(handle);
-}
-
-static void do_mkdir(unsigned int handle, char *path)
-{
- if (!xs_mkdir(handles[handle], txh[handle], path))
- failed(handle);
-}
-
-static void do_rm(unsigned int handle, char *path)
-{
- if (!xs_rm(handles[handle], txh[handle], path))
- failed(handle);
-}
-
-static void do_getperm(unsigned int handle, char *path)
-{
- unsigned int i, num;
- struct xs_permissions *perms;
-
- perms = xs_get_permissions(handles[handle], txh[handle], path, &num);
- if (!perms) {
- failed(handle);
- return;
- }
-
- for (i = 0; i < num; i++) {
- char *permstring;
-
- switch (perms[i].perms) {
- case XS_PERM_NONE:
- permstring = "NONE";
- break;
- case XS_PERM_WRITE:
- permstring = "WRITE";
- break;
- case XS_PERM_READ:
- permstring = "READ";
- break;
- case XS_PERM_READ|XS_PERM_WRITE:
- permstring = "READ/WRITE";
- break;
- default:
- barf("bad perm value %i", perms[i].perms);
- }
-
- if (handle)
- output("%i:%i %s\n", handle, perms[i].id, permstring);
- else
- output("%i %s\n", perms[i].id, permstring);
- }
- free(perms);
-}
-
-static void do_setperm(unsigned int handle, char *path, char *line)
-{
- unsigned int i;
- struct xs_permissions perms[100];
-
- strtok(line, " \t\n");
- strtok(NULL, " \t\n");
- for (i = 0; ; i++) {
- char *arg = strtok(NULL, " \t\n");
- if (!arg)
- break;
- perms[i].id = atoi(arg);
- arg = strtok(NULL, " \t\n");
- if (!arg)
- break;
- if (streq(arg, "WRITE"))
- perms[i].perms = XS_PERM_WRITE;
- else if (streq(arg, "READ"))
- perms[i].perms = XS_PERM_READ;
- else if (streq(arg, "READ/WRITE"))
- perms[i].perms = XS_PERM_READ|XS_PERM_WRITE;
- else if (streq(arg, "NONE"))
- perms[i].perms = XS_PERM_NONE;
- else
- barf("bad flags %s\n", arg);
- }
-
- if (!xs_set_permissions(handles[handle], txh[handle], path, perms, i))
- failed(handle);
-}
-
-static void do_watch(unsigned int handle, const char *node, const char *token,
- bool swallow_event)
-{
- if (!xs_watch(handles[handle], node, token))
- failed(handle);
-
- /* Convenient for testing... */
- if (swallow_event) {
- unsigned int num;
- char **vec = xs_read_watch(handles[handle], &num);
- if (!vec ||
- !streq(vec[XS_WATCH_PATH], node) ||
- !streq(vec[XS_WATCH_TOKEN], token))
- failed(handle);
- }
-}
-
-static void set_timeout(void)
-{
- struct itimerval timeout;
-
- timeout.it_value.tv_sec = timeout_ms / 1000;
- timeout.it_value.tv_usec = (timeout_ms * 1000) % 1000000;
- timeout.it_interval.tv_sec = timeout.it_interval.tv_usec = 0;
- setitimer(ITIMER_REAL, &timeout, NULL);
-}
-
-static void disarm_timeout(void)
-{
- struct itimerval timeout;
-
- timeout.it_value.tv_sec = 0;
- timeout.it_value.tv_usec = 0;
- setitimer(ITIMER_REAL, &timeout, NULL);
-}
-
-static void do_waitwatch(unsigned int handle)
-{
- char **vec;
- struct timeval tv = {.tv_sec = timeout_ms/1000,
- .tv_usec = (timeout_ms*1000)%1000000 };
- fd_set set;
- unsigned int num;
-
- if (xs_fileno(handles[handle]) != -2) {
- /* Manually select here so we can time out gracefully. */
- FD_ZERO(&set);
- FD_SET(xs_fileno(handles[handle]), &set);
- disarm_timeout();
- if (select(xs_fileno(handles[handle])+1, &set,
- NULL, NULL, &tv) == 0) {
- errno = ETIMEDOUT;
- failed(handle);
- return;
- }
- set_timeout();
- }
-
- vec = xs_read_watch(handles[handle], &num);
- if (!vec) {
- failed(handle);
- return;
- }
-
- if (handle)
- output("%i:%s:%s\n", handle,
- vec[XS_WATCH_PATH], vec[XS_WATCH_TOKEN]);
- else
- output("%s:%s\n", vec[XS_WATCH_PATH], vec[XS_WATCH_TOKEN]);
- free(vec);
-}
-
-static void do_unwatch(unsigned int handle, const char *node, const char *token)
-{
- if (!xs_unwatch(handles[handle], node, token))
- failed(handle);
-}
-
-static void do_start(unsigned int handle)
-{
- txh[handle] = xs_transaction_start(handles[handle]);
- if (txh[handle] == XBT_NULL)
- failed(handle);
-}
-
-static void do_end(unsigned int handle, bool abort)
-{
- if (!xs_transaction_end(handles[handle], txh[handle], abort))
- failed(handle);
- txh[handle] = XBT_NULL;
-}
-
-static void do_introduce(unsigned int handle,
- const char *domid,
- const char *mfn,
- const char *eventchn,
- const char *path)
-{
- unsigned int i;
- int fd;
-
- /* This mechanism is v. slow w. valgrind running. */
- timeout_ms = 5000;
-
- /* We poll, so ignore signal */
- signal(SIGUSR2, SIG_IGN);
- for (i = 0; i < ARRAY_SIZE(handles); i++)
- if (!handles[i])
- break;
-
- fd = open("/tmp/xcmap", O_RDWR);
- /* Set shared comms page. */
- interface = mmap(NULL, getpagesize(), PROT_WRITE|PROT_READ,
- MAP_SHARED,fd,0);
- if (interface == MAP_FAILED)
- barf_perror("Failed to map /tmp/xcmap page");
- close(fd);
-
- /* Tell them the event channel and our PID. */
- *(int *)((void *)interface + 32) = getpid();
- *(uint16_t *)((void *)interface + 36) = atoi(eventchn);
-
- if (!xs_introduce_domain(handles[handle], atoi(domid),
- atol(mfn), atoi(eventchn))) {
- failed(handle);
- munmap(interface, getpagesize());
- return;
- }
- output("handle is %i\n", i);
-
- /* Create new handle. */
- handles[i] = new(struct xs_handle);
- handles[i]->fd = -2;
-
- /* Read in daemon pid. */
- daemon_pid = *(int *)((void *)interface + 32);
-}
-
-static void do_release(unsigned int handle, const char *domid)
-{
- if (!xs_release_domain(handles[handle], atoi(domid)))
- failed(handle);
-}
-
-static int strptrcmp(const void *a, const void *b)
-{
- return strcmp(*(char **)a, *(char **)b);
-}
-
-static void sort_dir(char **dir, unsigned int num)
-{
- qsort(dir, num, sizeof(char *), strptrcmp);
-}
-
-static void dump_dir(unsigned int handle,
- const char *node,
- char **dir,
- unsigned int numdirs,
- unsigned int depth)
-{
- unsigned int i;
- char spacing[depth+1];
-
- memset(spacing, ' ', depth);
- spacing[depth] = '\0';
-
- sort_dir(dir, numdirs);
-
- for (i = 0; i < numdirs; i++) {
- struct xs_permissions *perms;
- unsigned int j, numperms;
- unsigned int len;
- char *contents;
- unsigned int subnum;
- char **subdirs;
- char subnode[strlen(node) + 1 + strlen(dir[i]) + 1];
-
- sprintf(subnode, "%s/%s", node, dir[i]);
-
- perms = xs_get_permissions(handles[handle], txh[handle],
- subnode,&numperms);
- if (!perms) {
- failed(handle);
- return;
- }
-
- output("%s%s: ", spacing, dir[i]);
- for (j = 0; j < numperms; j++) {
- char buffer[100];
- if (!xs_perm_to_string(&perms[j], buffer))
- barf("perm to string");
- output("%s ", buffer);
- }
- free(perms);
- output("\n");
-
- /* Even directories can have contents. */
- contents = xs_read(handles[handle], txh[handle],
- subnode, &len);
- if (!contents) {
- if (errno != EISDIR)
- failed(handle);
- } else {
- output(" %s(%.*s)\n", spacing, len, contents);
- free(contents);
- }
-
- /* Every node is a directory. */
- subdirs = xs_directory(handles[handle], txh[handle],
- subnode, &subnum);
- if (!subdirs) {
- failed(handle);
- return;
- }
- dump_dir(handle, subnode, subdirs, subnum, depth+1);
- free(subdirs);
- }
-}
-
-static void dump(int handle)
-{
- char **subdirs;
- unsigned int subnum;
-
- subdirs = xs_directory(handles[handle], txh[handle], "/", &subnum);
- if (!subdirs) {
- failed(handle);
- return;
- }
-
- dump_dir(handle, "", subdirs, subnum, 0);
- free(subdirs);
-}
-
-static int handle;
-
-static void alarmed(int sig __attribute__((unused)))
-{
- if (handle) {
- char handlename[10];
- sprintf(handlename, "%u:", handle);
- write(STDOUT_FILENO, handlename, strlen(handlename));
- }
- write(STDOUT_FILENO, command, strlen(command));
- write(STDOUT_FILENO, " timeout\n", strlen(" timeout\n"));
- exit(1);
-}
-
-static void do_command(unsigned int default_handle, char *line)
-{
- char *endp;
-
- if (print_input)
- printf("%i> %s", ++linenum, line);
-
- if (strspn(line, " \n") == strlen(line))
- return;
- if (strstarts(line, "#"))
- return;
-
- handle = strtoul(line, &endp, 10);
- if (endp != line)
- memmove(line, endp+1, strlen(endp));
- else
- handle = default_handle;
-
- command = arg(line, 0);
- if (!handles[handle]) {
- if (readonly)
- handles[handle] = xs_daemon_open_readonly();
- else
- handles[handle] = xs_daemon_open();
- if (!handles[handle])
- barf_perror("Opening connection to daemon");
- }
-
- if (!timeout_suppressed)
- set_timeout();
- timeout_suppressed = false;
-
- if (streq(command, "dir"))
- do_dir(handle, arg(line, 1));
- else if (streq(command, "read"))
- do_read(handle, arg(line, 1));
- else if (streq(command, "write"))
- do_write(handle, arg(line, 1), arg(line, 2));
- else if (streq(command, "setid"))
- do_setid(handle, arg(line, 1));
- else if (streq(command, "mkdir"))
- do_mkdir(handle, arg(line, 1));
- else if (streq(command, "rm"))
- do_rm(handle, arg(line, 1));
- else if (streq(command, "getperm"))
- do_getperm(handle, arg(line, 1));
- else if (streq(command, "setperm"))
- do_setperm(handle, arg(line, 1), line);
- else if (streq(command, "watch"))
- do_watch(handle, arg(line, 1), arg(line, 2), true);
- else if (streq(command, "watchnoack"))
- do_watch(handle, arg(line, 1), arg(line, 2), false);
- else if (streq(command, "waitwatch"))
- do_waitwatch(handle);
- else if (streq(command, "unwatch"))
- do_unwatch(handle, arg(line, 1), arg(line, 2));
- else if (streq(command, "close")) {
- xs_daemon_close(handles[handle]);
- handles[handle] = NULL;
- txh[handle] = XBT_NULL;
- } else if (streq(command, "start"))
- do_start(handle);
- else if (streq(command, "commit"))
- do_end(handle, false);
- else if (streq(command, "abort"))
- do_end(handle, true);
- else if (streq(command, "introduce"))
- do_introduce(handle, arg(line, 1), arg(line, 2),
- arg(line, 3), arg(line, 4));
- else if (streq(command, "release"))
- do_release(handle, arg(line, 1));
- else if (streq(command, "dump"))
- dump(handle);
- else if (streq(command, "sleep")) {
- disarm_timeout();
- usleep(atoi(arg(line, 1)) * 1000);
- } else if (streq(command, "expect"))
- expect(line);
- else if (streq(command, "notimeout"))
- timeout_suppressed = true;
- else if (streq(command, "readonly")) {
- readonly = true;
- xs_daemon_close(handles[handle]);
- handles[handle] = NULL;
- } else if (streq(command, "readwrite")) {
- readonly = false;
- xs_daemon_close(handles[handle]);
- handles[handle] = NULL;
- } else
- barf("Unknown command %s", command);
- fflush(stdout);
- disarm_timeout();
-
- /* Check expectations. */
- if (!streq(command, "expect")) {
- struct expect *i = list_top(&expects, struct expect, list);
-
- if (i)
- barf("Expected '%s', didn't happen\n", i->pattern);
- }
-}
-
-static struct option options[] = { { "readonly", 0, NULL, 'r' },
- { "no-timeout", 0, NULL, 't' },
- { NULL, 0, NULL, 0 } };
-
-int main(int argc, char *argv[])
-{
- int opt;
- char line[1024];
-
- while ((opt = getopt_long(argc, argv, "xrt", options, NULL)) != -1) {
- switch (opt) {
- case 'r':
- readonly = true;
- break;
- case 't':
- timeout_ms = 0;
- break;
- case 'x':
- print_input = true;
- break;
- }
- }
-
- if (optind + 1 == argc) {
- int fd = open(argv[optind], O_RDONLY);
- if (!fd)
- barf_perror("Opening %s", argv[optind]);
- dup2(fd, STDIN_FILENO);
- } else if (optind != argc)
- usage();
-
-
- signal(SIGALRM, alarmed);
- while (fgets(line, sizeof(line), stdin))
- do_command(0, line);
-
- return 0;
-}
-
-/*
- * Local variables:
- * c-file-style: "linux"
- * indent-tabs-mode: t
- * c-indent-level: 8
- * c-basic-offset: 8
- * tab-width: 8
- * End:
- */
diff --git a/tools/xentrace/xentrace.c b/tools/xentrace/xentrace.c
index 45fb99f7e7..ad06778592 100644
--- a/tools/xentrace/xentrace.c
+++ b/tools/xentrace/xentrace.c
@@ -256,7 +256,7 @@ struct t_rec **init_rec_ptrs(struct t_buf **meta, unsigned int num)
*/
unsigned int get_num_cpus(void)
{
- xc_physinfo_t physinfo;
+ xc_physinfo_t physinfo = { 0 };
int xc_handle = xc_interface_open();
int ret;
diff --git a/tools/xm-test/tests/info/02_info_compiledata_pos.py b/tools/xm-test/tests/info/02_info_compiledata_pos.py
index 189fce17cb..9430ecf62f 100644
--- a/tools/xm-test/tests/info/02_info_compiledata_pos.py
+++ b/tools/xm-test/tests/info/02_info_compiledata_pos.py
@@ -18,9 +18,7 @@ map = {}
for line in lines:
pieces = line.split(" : ", 1)
- if len(pieces) < 2:
- FAIL("Found invalid line: [%s]" % line)
- else:
+ if len(pieces) > 1:
map[pieces[0]] = pieces[1]
for field in ["cores_per_socket", "threads_per_core", "cpu_mhz",