[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [VTPM_TOOLS] Hotplug script enabled the vtpm manager and removed the
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxx # Node ID 8589cdd096360970933a7c9112f2925c52d08696 # Parent 18587d3e94c8c3a6ccdf9bc5965eea426e6df87d [VTPM_TOOLS] Hotplug script enabled the vtpm manager and removed the control messages from the BE. Signed-off-by: Vincent Scarlata <vincent.r.scarlata@xxxxxxxxx> --- linux-2.6-xen-sparse/drivers/xen/tpmback/common.h | 2 linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c | 89 ------------- linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c | 23 --- tools/examples/Makefile | 2 tools/examples/vtpm-impl | 136 +++++++++++++++++++++ tools/vtpm_manager/manager/dmictl.c | 57 +++++--- tools/vtpm_manager/manager/securestorage.c | 29 +++- tools/vtpm_manager/manager/vtpm_manager.c | 3 tools/vtpm_manager/manager/vtpm_manager.h | 10 + tools/vtpm_manager/manager/vtpm_manager_handler.c | 75 ++++++----- tools/vtpm_manager/manager/vtpmd.c | 40 +++--- tools/vtpm_manager/manager/vtpmpriv.h | 13 +- tools/vtpm_manager/manager/vtsp.c | 11 + tools/vtpm_manager/manager/vtsp.h | 2 tools/vtpm_manager/tcs/tcs.c | 43 ++++++ tools/vtpm_manager/tcs/tcs.h | 5 tools/vtpm_manager/util/tcg.h | 5 17 files changed, 342 insertions(+), 203 deletions(-) diff -r 18587d3e94c8 -r 8589cdd09636 linux-2.6-xen-sparse/drivers/xen/tpmback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Tue Jun 27 11:14:19 2006 +0100 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Tue Jun 27 11:15:48 2006 +0100 @@ -63,8 +63,6 @@ void tpmif_xenbus_exit(void); void tpmif_xenbus_exit(void); int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn); irqreturn_t tpmif_be_int(int irq, void *dev_id, struct pt_regs *regs); -int tpmif_vtpm_open(tpmif_t *tpmif, domid_t domain, u32 instance); -int tpmif_vtpm_close(u32 instance); int vtpm_release_packets(tpmif_t * tpmif, int send_msgs); diff -r 18587d3e94c8 -r 8589cdd09636 linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Tue Jun 27 11:14:19 2006 +0100 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Tue Jun 27 11:15:48 2006 +0100 @@ -685,95 +685,6 @@ static struct miscdevice vtpms_miscdevic }; /*************************************************************** - Virtual TPM functions and data stuctures -***************************************************************/ - -static u8 create_cmd[] = { - 1, 193, /* 0: TPM_TAG_RQU_COMMAMD */ - 0, 0, 0, 19, /* 2: length */ - 0, 0, 0, 0x1, /* 6: VTPM_ORD_OPEN */ - 0, /* 10: VTPM type */ - 0, 0, 0, 0, /* 11: domain id */ - 0, 0, 0, 0 /* 15: instance id */ -}; - -int tpmif_vtpm_open(tpmif_t * tpmif, domid_t domid, u32 instance) -{ - int rc = 0; - struct packet *pak; - - pak = packet_alloc(tpmif, - sizeof (create_cmd), - create_cmd[1], - PACKET_FLAG_DISCARD_RESPONSE | - PACKET_FLAG_CHECK_RESPONSESTATUS); - if (pak) { - u8 buf[sizeof (create_cmd)]; - u32 domid_no = htonl((u32) domid); - u32 instance_no = htonl(instance); - - memcpy(buf, create_cmd, sizeof (create_cmd)); - - memcpy(&buf[11], &domid_no, sizeof (u32)); - memcpy(&buf[15], &instance_no, sizeof (u32)); - - /* copy the buffer into the packet */ - rc = packet_set(pak, buf, sizeof (buf)); - - if (rc == 0) { - pak->tpm_instance = 0; - rc = vtpm_queue_packet(pak); - } - if (rc < 0) { - /* could not be queued or built */ - packet_free(pak); - } - } else { - rc = -ENOMEM; - } - return rc; -} - -static u8 destroy_cmd[] = { - 1, 193, /* 0: TPM_TAG_RQU_COMMAMD */ - 0, 0, 0, 14, /* 2: length */ - 0, 0, 0, 0x2, /* 6: VTPM_ORD_CLOSE */ - 0, 0, 0, 0 /* 10: instance id */ -}; - -int tpmif_vtpm_close(u32 instid) -{ - int rc = 0; - struct packet *pak; - - pak = packet_alloc(NULL, - sizeof (destroy_cmd), - destroy_cmd[1], PACKET_FLAG_DISCARD_RESPONSE); - if (pak) { - u8 buf[sizeof (destroy_cmd)]; - u32 instid_no = htonl(instid); - - memcpy(buf, destroy_cmd, sizeof (destroy_cmd)); - memcpy(&buf[10], &instid_no, sizeof (u32)); - - /* copy the buffer into the packet */ - rc = packet_set(pak, buf, sizeof (buf)); - - if (rc == 0) { - pak->tpm_instance = 0; - rc = vtpm_queue_packet(pak); - } - if (rc < 0) { - /* could not be queued or built */ - packet_free(pak); - } - } else { - rc = -ENOMEM; - } - return rc; -} - -/*************************************************************** Utility functions ***************************************************************/ diff -r 18587d3e94c8 -r 8589cdd09636 linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Tue Jun 27 11:14:19 2006 +0100 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Tue Jun 27 11:15:48 2006 +0100 @@ -154,11 +154,6 @@ static void frontend_changed(struct xenb break; case XenbusStateClosed: - /* - * Notify the vTPM manager about the front-end - * having left. - */ - tpmif_vtpm_close(be->instance); device_unregister(&be->dev->dev); tpmback_remove(dev); break; @@ -177,28 +172,10 @@ static void frontend_changed(struct xenb static void maybe_connect(struct backend_info *be) { - int err; - if (be->tpmif == NULL || be->tpmif->status == CONNECTED) return; connect(be); - - /* - * Notify the vTPM manager about a new front-end. - */ - err = tpmif_vtpm_open(be->tpmif, - be->frontend_id, - be->instance); - if (err) { - xenbus_dev_error(be->dev, err, - "queueing vtpm open packet"); - /* - * Should close down this device and notify FE - * about closure. - */ - return; - } } diff -r 18587d3e94c8 -r 8589cdd09636 tools/examples/Makefile --- a/tools/examples/Makefile Tue Jun 27 11:14:19 2006 +0100 +++ b/tools/examples/Makefile Tue Jun 27 11:15:48 2006 +0100 @@ -32,7 +32,7 @@ XEN_SCRIPT_DATA = xen-script-common.sh l XEN_SCRIPT_DATA = xen-script-common.sh locking.sh logging.sh XEN_SCRIPT_DATA += xen-hotplug-common.sh xen-network-common.sh vif-common.sh XEN_SCRIPT_DATA += block-common.sh vtpm-common.sh vtpm-hotplug-common.sh -XEN_SCRIPT_DATA += vtpm-migration.sh +XEN_SCRIPT_DATA += vtpm-migration.sh vtpm-impl XEN_HOTPLUG_DIR = /etc/hotplug XEN_HOTPLUG_SCRIPTS = xen-backend.agent diff -r 18587d3e94c8 -r 8589cdd09636 tools/vtpm_manager/manager/dmictl.c --- a/tools/vtpm_manager/manager/dmictl.c Tue Jun 27 11:14:19 2006 +0100 +++ b/tools/vtpm_manager/manager/dmictl.c Tue Jun 27 11:15:48 2006 +0100 @@ -76,14 +76,13 @@ TPM_RESULT VTPM_Handle_New_DMI(const buf VTPM_DMI_RESOURCE *new_dmi=NULL; TPM_RESULT status=TPM_FAIL; - BYTE type; - UINT32 dmi_id, domain_id, *dmi_id_key; + BYTE type, startup_mode; + UINT32 dmi_id, *dmi_id_key=NULL; if (param_buf == NULL) { // Assume creation of Dom 0 control - type = 0; - domain_id = VTPM_CTL_DM; + type = VTPM_TYPE_NON_MIGRATABLE; dmi_id = VTPM_CTL_DM; - } else if (buffer_len(param_buf) != sizeof(BYTE) + sizeof(UINT32) *2) { + } else if (buffer_len(param_buf) != sizeof(BYTE) + sizeof(BYTE) + sizeof(UINT32)) { vtpmloginfo(VTPM_LOG_VTPM, "New DMI command wrong length: %d.\n", buffer_len(param_buf)); status = TPM_BAD_PARAMETER; goto abort_egress; @@ -91,13 +90,13 @@ TPM_RESULT VTPM_Handle_New_DMI(const buf vtpm_globals->connected_dmis++; // Put this here so we don't count Dom0 BSG_UnpackList( param_buf->bytes, 3, BSG_TYPE_BYTE, &type, - BSG_TYPE_UINT32, &domain_id, + BSG_TYPE_BYTE, &startup_mode, BSG_TYPE_UINT32, &dmi_id); } - + new_dmi = (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globals->dmi_map, &dmi_id); if (new_dmi == NULL) { - vtpmloginfo(VTPM_LOG_VTPM, "Creating new DMI instance %d attached on domain %d.\n", dmi_id, domain_id); + vtpmloginfo(VTPM_LOG_VTPM, "Creating new DMI instance %d attached.\n", dmi_id ); // Brand New DMI. Initialize the persistent pieces if ((new_dmi = (VTPM_DMI_RESOURCE *) malloc (sizeof(VTPM_DMI_RESOURCE))) == NULL) { status = TPM_RESOURCES; @@ -106,32 +105,44 @@ TPM_RESULT VTPM_Handle_New_DMI(const buf memset(new_dmi, 0, sizeof(VTPM_DMI_RESOURCE)); new_dmi->dmi_id = dmi_id; new_dmi->connected = FALSE; + + if (type != VTPM_TYPE_MIGRATED) { + new_dmi->dmi_type = type; + } else { + vtpmlogerror(VTPM_LOG_VTPM, "Creation of VTPM with illegal type.\n"); + status = TPM_BAD_PARAMETER; + goto free_egress; + } if ((dmi_id_key = (UINT32 *) malloc (sizeof(UINT32))) == NULL) { status = TPM_RESOURCES; - goto abort_egress; + goto free_egress; } *dmi_id_key = new_dmi->dmi_id; // install into map if (!hashtable_insert(vtpm_globals->dmi_map, dmi_id_key, new_dmi)){ - free(new_dmi); - free(dmi_id_key); + vtpmlogerror(VTPM_LOG_VTPM, "Failed to insert instance into table. Aborting.\n", dmi_id); status = TPM_FAIL; - goto egress; + goto free_egress; } } else - vtpmloginfo(VTPM_LOG_VTPM, "Re-attaching DMI instance %d on domain %d .\n", dmi_id, domain_id); + vtpmloginfo(VTPM_LOG_VTPM, "Re-attaching DMI instance %d.\n", dmi_id); if (new_dmi->connected) { vtpmlogerror(VTPM_LOG_VTPM, "Attempt to re-attach, currently attached instance %d. Ignoring\n", dmi_id); status = TPM_BAD_PARAMETER; - goto egress; - } - + goto abort_egress; + } + + if (type == VTPM_TYPE_MIGRATED) { + vtpmlogerror(VTPM_LOG_VTPM, "Attempt to re-attach previously migrated instance %d without recovering first. Ignoring\n", dmi_id); + status = TPM_BAD_PARAMETER; + goto abort_egress; + } + // Initialize the Non-persistent pieces - new_dmi->dmi_domain_id = domain_id; new_dmi->NVMLocation = NULL; new_dmi->TCSContext = 0; @@ -144,9 +155,13 @@ TPM_RESULT VTPM_Handle_New_DMI(const buf // Design specific new DMI code. // Includes: create IPCs, Measuring DMI, and maybe launching DMI - status = VTPM_New_DMI_Extra(new_dmi); - goto egress; - + status = VTPM_New_DMI_Extra(new_dmi, startup_mode); + goto egress; + + free_egress: // Error that requires freeing of newly allocated dmi + free(new_dmi); + free(dmi_id_key); + abort_egress: vtpmlogerror(VTPM_LOG_VTPM, "Failed to create DMI id=%d due to status=%s. Cleaning.\n", dmi_id, tpm_get_error_name(status)); close_dmi(new_dmi ); @@ -221,7 +236,7 @@ TPM_RESULT VTPM_Handle_Delete_DMI( const goto abort_egress; } - //TODO: Automatically delete file dmi_res->NVMLocation + //vtpm scripts delete file dmi_res->NVMLocation for us // Close DMI first TPMTRYRETURN(close_dmi( dmi_res )); diff -r 18587d3e94c8 -r 8589cdd09636 tools/vtpm_manager/manager/securestorage.c --- a/tools/vtpm_manager/manager/securestorage.c Tue Jun 27 11:14:19 2006 +0100 +++ b/tools/vtpm_manager/manager/securestorage.c Tue Jun 27 11:15:48 2006 +0100 @@ -190,8 +190,7 @@ TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI long bytes_written; buffer_t sealed_NVM; - - vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Save_NVMing[%d]: 0x\n", buffer_len(inbuf)); + vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Saving %d bytes of NVM.\n", buffer_len(inbuf)); TPMTRYRETURN( envelope_encrypt(inbuf, &vtpm_globals->storageKey, @@ -310,6 +309,7 @@ TPM_RESULT VTPM_SaveManagerData(void) { UINT32 bootKeySize = buffer_len(&vtpm_globals->bootKeyWrap); struct pack_buf_t storage_key_pack = {storageKeySize, vtpm_globals->storageKeyWrap.bytes}; struct pack_buf_t boot_key_pack = {bootKeySize, vtpm_globals->bootKeyWrap.bytes}; + BYTE vtpm_manager_gen = VTPM_MANAGER_GEN; struct hashtable_itr *dmi_itr; VTPM_DMI_RESOURCE *dmi_res; @@ -321,7 +321,8 @@ TPM_RESULT VTPM_SaveManagerData(void) { boot_key_size = sizeof(UINT32) + // bootkeysize bootKeySize; // boot key - TPMTRYRETURN(buffer_init(&clear_flat_global, 3*sizeof(TPM_DIGEST) + // Auths + TPMTRYRETURN(buffer_init(&clear_flat_global,sizeof(BYTE) + // manager version + 3*sizeof(TPM_DIGEST) + // Auths sizeof(UINT32) +// storagekeysize storageKeySize, NULL) ); // storage key @@ -332,7 +333,8 @@ TPM_RESULT VTPM_SaveManagerData(void) { boot_key_size = BSG_PackList(flat_boot_key, 1, BSG_TPM_SIZE32_DATA, &boot_key_pack); - BSG_PackList(clear_flat_global.bytes, 3, + BSG_PackList(clear_flat_global.bytes, 4, + BSG_TYPE_BYTE, &vtpm_manager_gen, BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth, BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth, BSG_TPM_SIZE32_DATA, &storage_key_pack); @@ -348,7 +350,7 @@ TPM_RESULT VTPM_SaveManagerData(void) { flat_dmis = (BYTE *) malloc( (hashtable_count(vtpm_globals->dmi_map) - 1) * // num DMIS (-1 for Dom0) - (sizeof(UINT32) + 2*sizeof(TPM_DIGEST)) ); // Per DMI info + (sizeof(UINT32) +sizeof(BYTE) + 2*sizeof(TPM_DIGEST)) ); // Per DMI info dmi_itr = hashtable_iterator(vtpm_globals->dmi_map); do { @@ -360,8 +362,9 @@ TPM_RESULT VTPM_SaveManagerData(void) { continue; - flat_dmis_size += BSG_PackList( flat_dmis + flat_dmis_size, 3, + flat_dmis_size += BSG_PackList( flat_dmis + flat_dmis_size, 4, BSG_TYPE_UINT32, &dmi_res->dmi_id, + BSG_TYPE_BYTE, &dmi_res->dmi_type, BSG_TPM_DIGEST, &dmi_res->NVM_measurement, BSG_TPM_DIGEST, &dmi_res->DMI_measurement); @@ -408,6 +411,7 @@ TPM_RESULT VTPM_LoadManagerData(void) { buffer_t unsealed_data; struct pack_buf_t storage_key_pack, boot_key_pack; UINT32 *dmi_id_key, enc_size; + BYTE vtpm_manager_gen; VTPM_DMI_RESOURCE *dmi_res; struct stat file_stat; @@ -458,8 +462,14 @@ TPM_RESULT VTPM_LoadManagerData(void) { &unsealed_data) ); step_size += enc_size; + if (*unsealed_data.bytes != VTPM_MANAGER_GEN) { + // Once there is more than one gen, this will include some compatability stuff + vtpmlogerror(VTPM_LOG_VTPM, "Warning: Manager Data file is gen %d, which this manager is gen %d.\n", vtpm_manager_gen, VTPM_MANAGER_GEN); + } + // Global Values needing to be saved - BSG_UnpackList( unsealed_data.bytes, 3, + BSG_UnpackList( unsealed_data.bytes, 4, + BSG_TYPE_BYTE, &vtpm_manager_gen, BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth, BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth, BSG_TPM_SIZE32_DATA, &storage_key_pack); @@ -469,7 +479,7 @@ TPM_RESULT VTPM_LoadManagerData(void) { // Per DMI values to be saved while ( step_size < fh_size ){ - if (fh_size - step_size < (long) (sizeof(UINT32) + 2*sizeof(TPM_DIGEST))) { + if (fh_size - step_size < (long) (sizeof(UINT32) + sizeof(BYTE) + 2*sizeof(TPM_DIGEST))) { vtpmlogerror(VTPM_LOG_VTPM, "Encountered %ld extra bytes at end of manager state.\n", fh_size-step_size); step_size = fh_size; } else { @@ -478,8 +488,9 @@ TPM_RESULT VTPM_LoadManagerData(void) { dmi_res->connected = FALSE; - step_size += BSG_UnpackList(flat_table + step_size, 3, + step_size += BSG_UnpackList(flat_table + step_size, 4, BSG_TYPE_UINT32, &dmi_res->dmi_id, + BSG_TYPE_BYTE, &dmi_res->dmi_type, BSG_TPM_DIGEST, &dmi_res->NVM_measurement, BSG_TPM_DIGEST, &dmi_res->DMI_measurement); diff -r 18587d3e94c8 -r 8589cdd09636 tools/vtpm_manager/manager/vtpm_manager.c --- a/tools/vtpm_manager/manager/vtpm_manager.c Tue Jun 27 11:14:19 2006 +0100 +++ b/tools/vtpm_manager/manager/vtpm_manager.c Tue Jun 27 11:15:48 2006 +0100 @@ -168,6 +168,7 @@ TPM_RESULT VTPM_Create_Manager(){ &vtpm_globals->bootKey, TRUE ) ); + TPMTRYRETURN( VTSP_SaveState(vtpm_globals->manager_tcs_handle) ); goto egress; abort_egress: @@ -218,7 +219,7 @@ TPM_RESULT VTPM_Init_Manager() { &vtpm_globals->keyAuth) ); vtpm_globals->keyAuth.fContinueAuthSession = TRUE; - // If failed, create new Manager. + // If failed, create new Manager. serviceStatus = VTPM_LoadManagerData(); if (serviceStatus == TPM_IOERROR) { vtpmloginfo(VTPM_LOG_VTPM, "Failed to read manager file. Assuming first time initialization.\n"); diff -r 18587d3e94c8 -r 8589cdd09636 tools/vtpm_manager/manager/vtpm_manager.h --- a/tools/vtpm_manager/manager/vtpm_manager.h Tue Jun 27 11:14:19 2006 +0100 +++ b/tools/vtpm_manager/manager/vtpm_manager.h Tue Jun 27 11:15:48 2006 +0100 @@ -73,6 +73,12 @@ #define VTPM_RESTORE_CONTEXT_FAILED 4 #define VTPM_INVALID_REQUEST 5 +//*********************** Parameter Values ************************* +#define VTPM_TYPE_NON_MIGRATABLE 0x00 +#define VTPM_TYPE_MIGRATABLE 0x01 +#define VTPM_TYPE_MIGRATED 0xFF // VTPM has been migrated. + // VTPM can be recovered or deleted only + /******************* Command Parameter API ************************* VTPM Command Format @@ -94,8 +100,8 @@ VTPM Response Format VTPM_Open: Input Parameters: - Domain_type: 1 byte - domain_id: 4 bytes + Domain_type: 1 byte + startup_mode: 1 byte // Cold Boot = 1, resume = 2, deactive = 3 instance_id: 4 bytes Output Parameters: None diff -r 18587d3e94c8 -r 8589cdd09636 tools/vtpm_manager/manager/vtpm_manager_handler.c --- a/tools/vtpm_manager/manager/vtpm_manager_handler.c Tue Jun 27 11:14:19 2006 +0100 +++ b/tools/vtpm_manager/manager/vtpm_manager_handler.c Tue Jun 27 11:15:48 2006 +0100 @@ -78,13 +78,14 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ip BOOL is_priv, char *thread_name) { TPM_RESULT status = TPM_FAIL; // Should never return - UINT32 dmi, in_param_size, cmd_size, out_param_size, out_message_size, out_message_size_full; - BYTE *cmd_header, *in_param, *out_message; + UINT32 dmi, in_param_size, cmd_size, out_param_size, out_message_size, reply_size; + BYTE *cmd_header=NULL, *in_param=NULL, *out_message=NULL, *reply; buffer_t *command_buf=NULL, *result_buf=NULL; TPM_TAG tag; TPM_COMMAND_CODE ord; VTPM_DMI_RESOURCE *dmi_res; int size_read, size_write, i; + BOOL add_header=TRUE; // This indicates to prepend a header on result_buf before sending cmd_header = (BYTE *) malloc(VTPM_COMMAND_HEADER_SIZE_SRV); command_buf = (buffer_t *) malloc(sizeof(buffer_t)); @@ -100,7 +101,7 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ip // Read command header size_read = vtpm_ipc_read(rx_ipc_h, NULL, cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV); if (size_read > 0) { - vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "RECV[%d}: 0x", size_read); + vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "RECV[%d]: 0x", size_read); for (i=0; i<size_read; i++) vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cmd_header[i]); } else { @@ -165,6 +166,7 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ip (!dmi_res->connected) ) { vtpmhandlerlogerror(VTPM_LOG_VTPM, "Attempted access to non-existent or disconnected DMI %d. Aborting...\n", dmi); status = TPM_BAD_PARAMETER; + goto abort_with_error; } if (tag == VTPM_TAG_REQ) { @@ -176,9 +178,14 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ip status = vtpm_manager_handle_tpm_cmd(fw_tx_ipc_h, fw_rx_ipc_h, dmi_res, cmd_header, command_buf, result_buf, thread_name); // This means calling the DMI failed, not that the cmd failed in the DMI + // Since the return will be interpretted by a TPM app, all errors are IO_ERRORs to the app if (status != TPM_SUCCESS) { + status = TPM_IOERROR; goto abort_with_error; } + // Unlike all other commands, forwarded commands yield a result_buf that includes the DMI's status. This + // should be forwarded to the caller VM + add_header = FALSE; } else { // We are not supposed to forward TPM commands at all. int i; @@ -205,38 +212,43 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ip #ifndef VTPM_MULTI_VM abort_with_error: #endif - - // Prepend VTPM header with destination DM stamped - out_param_size = buffer_len(result_buf); - out_message_size = VTPM_COMMAND_HEADER_SIZE_CLT + out_param_size; - out_message_size_full = VTPM_COMMAND_HEADER_SIZE_SRV + out_param_size; - out_message = (BYTE *) malloc (out_message_size_full); - - BSG_PackList(out_message, 4, - BSG_TYPE_UINT32, (BYTE *) &dmi, - BSG_TPM_TAG, (BYTE *) &tag, - BSG_TYPE_UINT32, (BYTE *) &out_message_size, - BSG_TPM_RESULT, (BYTE *) &status); - - if (buffer_len(result_buf) > 0) - memcpy(out_message + VTPM_COMMAND_HEADER_SIZE_SRV, result_buf->bytes, out_param_size); - - //Note: Send message + dmi_id - size_write = vtpm_ipc_write(tx_ipc_h, dmi_res->tx_vtpm_ipc_h, out_message, out_message_size_full ); + + if (add_header) { + // Prepend VTPM header with destination DM stamped + out_param_size = buffer_len(result_buf); + out_message_size = VTPM_COMMAND_HEADER_SIZE_CLT + out_param_size; + reply_size = VTPM_COMMAND_HEADER_SIZE_SRV + out_param_size; + out_message = (BYTE *) malloc (reply_size); + reply = out_message; + + BSG_PackList(out_message, 4, + BSG_TYPE_UINT32, (BYTE *) &dmi, + BSG_TPM_TAG, (BYTE *) &tag, + BSG_TYPE_UINT32, (BYTE *) &out_message_size, + BSG_TPM_RESULT, (BYTE *) &status); + + if (buffer_len(result_buf) > 0) + memcpy(out_message + VTPM_COMMAND_HEADER_SIZE_SRV, result_buf->bytes, out_param_size); + //Note: Send message + dmi_id + } else { + reply = result_buf->bytes; + reply_size = buffer_len(result_buf); + } + size_write = vtpm_ipc_write(tx_ipc_h, (dmi_res ? dmi_res->tx_vtpm_ipc_h : NULL), reply, reply_size ); if (size_write > 0) { vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "SENT: 0x"); - for (i=0; i < out_message_size_full; i++) - vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", out_message[i]); + for (i=0; i < reply_size; i++) + vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", reply[i]); vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); } else { vtpmhandlerlogerror(VTPM_LOG_VTPM, "%s had error writing to ipc. Aborting... \n", thread_name); goto abort_command; } - free(out_message); - - if (size_write < (int)out_message_size_full) { - vtpmhandlerlogerror(VTPM_LOG_VTPM, "%s unable to write full command to ipc (%d/%d)\n", thread_name, size_write, out_message_size_full); + free(out_message); out_message=NULL; + + if (size_write < (int)reply_size) { + vtpmhandlerlogerror(VTPM_LOG_VTPM, "%s unable to write full command to ipc (%d/%d)\n", thread_name, size_write, reply_size); goto abort_command; } @@ -246,9 +258,7 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ip //free buffers bzero(cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV); //free(in_param); // This was converted to command_buf. No need to free - if (command_buf != result_buf) - buffer_free(result_buf); - + buffer_free(result_buf); buffer_free(command_buf); // If we have a write lock, save the manager table @@ -258,6 +268,7 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ip } vtpm_lock_unlock(); + add_header = TRUE; // Reset to the default } // End while(1) } @@ -369,6 +380,7 @@ TPM_RESULT vtpm_manager_handle_tpm_cmd(v dmi_cmd_size = VTPM_COMMAND_HEADER_SIZE_SRV; size_write = vtpm_ipc_write(tx_ipc_h, dmi_res->tx_tpm_ipc_h, cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV ); if (size_write > 0) { + vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "SENT (DMI): 0x"); for (i=0; i<VTPM_COMMAND_HEADER_SIZE_SRV; i++) vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cmd_header[i]); @@ -438,7 +450,8 @@ TPM_RESULT vtpm_manager_handle_tpm_cmd(v vtpmhandlerloginfomore(VTPM_LOG_VTPM, "\n"); } - if (buffer_init_convert(result_buf, adj_param_size, in_param) != TPM_SUCCESS) { + if ( (buffer_init(result_buf, VTPM_COMMAND_HEADER_SIZE_SRV, cmd_header) != TPM_SUCCESS) || + (buffer_append_raw(result_buf, adj_param_size, in_param) != TPM_SUCCESS) ) { vtpmhandlerlogerror(VTPM_LOG_VTPM, "Failed to setup buffers. Aborting...\n"); status = TPM_FAIL; goto abort_with_error; diff -r 18587d3e94c8 -r 8589cdd09636 tools/vtpm_manager/manager/vtpmd.c --- a/tools/vtpm_manager/manager/vtpmd.c Tue Jun 27 11:14:19 2006 +0100 +++ b/tools/vtpm_manager/manager/vtpmd.c Tue Jun 27 11:15:48 2006 +0100 @@ -64,14 +64,6 @@ #define VTPM_TX_HP_FNAME "/var/vtpm/fifos/to_console.fifo" #define VTPM_RX_HP_FNAME "/var/vtpm/fifos/from_console.fifo" - -#define GUEST_TX_FIFO "/var/vtpm/fifos/guest-to-%d.fifo" -#define GUEST_RX_FIFO "/var/vtpm/fifos/guest-from-all.fifo" - -#define VTPM_TX_FIFO "/var/vtpm/fifos/vtpm-to-%d.fifo" -#define VTPM_RX_FIFO "/var/vtpm/fifos/vtpm-from-all.fifo" - - struct vtpm_thread_params_s { vtpm_ipc_handle_t *tx_ipc_h; vtpm_ipc_handle_t *rx_ipc_h; @@ -113,7 +105,7 @@ void signal_handler(int reason) { struct sigaction ctl_c_handler; -TPM_RESULT VTPM_New_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res) { +TPM_RESULT VTPM_New_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res, BYTE startup_mode) { TPM_RESULT status = TPM_SUCCESS; int fh; @@ -150,14 +142,14 @@ TPM_RESULT VTPM_New_DMI_Extra(VTPM_DMI_R // Measure DMI // FIXME: This will measure DMI. Until then use a fixed DMI_Measurement value - // Also, this mechanism is specific to 1 VM. + // Also, this mechanism is specific to 1 VM architecture. /* fh = open(TPM_EMULATOR_PATH, O_RDONLY); stat_ret = fstat(fh, &file_stat); if (stat_ret == 0) dmi_size = file_stat.st_size; else { - vtpmlogerror(VTPM_LOG_VTPM, "Could not open tpm_emulator!!\n"); + vtpmlogerror(VTPM_LOG_VTPM, "Could not open vtpmd!!\n"); status = TPM_IOERROR; goto abort_egress; } @@ -179,10 +171,20 @@ TPM_RESULT VTPM_New_DMI_Extra(VTPM_DMI_R status = TPM_RESOURCES; goto abort_egress; } else if (pid == 0) { - if ( stat(dmi_res->NVMLocation, &file_info) == -1) + switch (startup_mode) { + case TPM_ST_CLEAR: execl (TPM_EMULATOR_PATH, "vtmpd", "clear", dmi_id_str, NULL); - else + break; + case TPM_ST_STATE: execl (TPM_EMULATOR_PATH, "vtpmd", "save", dmi_id_str, NULL); + break; + case TPM_ST_DEACTIVATED: + execl (TPM_EMULATOR_PATH, "vtpmd", "deactivated", dmi_id_str, NULL); + break; + default: + status = TPM_BAD_PARAMETER; + goto abort_egress; + } // Returning from these at all is an error. vtpmlogerror(VTPM_LOG_VTPM, "Could not exec to launch vtpm\n"); @@ -309,7 +311,7 @@ int main(int argc, char **argv) { be_thread_params.fw_tpm = TRUE; be_thread_params.fw_tx_ipc_h = NULL; be_thread_params.fw_rx_ipc_h = &rx_tpm_ipc_h; - be_thread_params.is_priv = TRUE; //FIXME: Change when HP is up + be_thread_params.is_priv = FALSE; be_thread_params.thread_name = "Backend Listener"; dmi_thread_params.tx_ipc_h = NULL; @@ -318,7 +320,7 @@ int main(int argc, char **argv) { dmi_thread_params.fw_tx_ipc_h = NULL; dmi_thread_params.fw_rx_ipc_h = NULL; dmi_thread_params.is_priv = FALSE; - dmi_thread_params.thread_name = "VTPM Listeners"; + dmi_thread_params.thread_name = "VTPM Listener"; hp_thread_params.tx_ipc_h = &tx_hp_ipc_h; hp_thread_params.rx_ipc_h = &rx_hp_ipc_h; @@ -345,10 +347,10 @@ int main(int argc, char **argv) { } -// if (pthread_create(&hp_thread, NULL, vtpm_manager_thread, &hp_thread_params) != 0) { -// vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch HP Thread.\n"); -// exit(-1); -// } + if (pthread_create(&hp_thread, NULL, vtpm_manager_thread, &hp_thread_params) != 0) { + vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch HP Thread.\n"); + exit(-1); + } //Join the other threads until exit time. pthread_join(be_thread, NULL); diff -r 18587d3e94c8 -r 8589cdd09636 tools/vtpm_manager/manager/vtpmpriv.h --- a/tools/vtpm_manager/manager/vtpmpriv.h Tue Jun 27 11:14:19 2006 +0100 +++ b/tools/vtpm_manager/manager/vtpmpriv.h Tue Jun 27 11:15:48 2006 +0100 @@ -40,15 +40,19 @@ #ifndef __VTPMPRIV_H__ #define __VTPMPRIV_H__ +#include "vtpm_manager.h" #include "tcg.h" #include "tcs.h" #include "buffer.h" #include "crypto.h" #include "vtpm_ipc.h" -#define STATE_FILE "/var/vtpm/VTPM" -#define DMI_NVM_FILE "/var/vtpm/vtpm_dm_%d.data" -#define VTPM_CTL_DM 0 +#define VTPM_MANAGER_GEN 2 // This is incremented when the manager's table + // is changed. It's used for backwards compatability + +#define STATE_FILE "/var/vtpm/VTPM" +#define DMI_NVM_FILE "/var/vtpm/vtpm_dm_%d.data" +#define VTPM_CTL_DM 0 // ------------------------ Private Structures ----------------------- typedef struct VTPM_DMI_RESOURCE_T { @@ -70,6 +74,7 @@ typedef struct VTPM_DMI_RESOURCE_T { // of NVM. // Persistent Information about DMI UINT32 dmi_id; + BYTE dmi_type; TPM_DIGEST NVM_measurement; // Equal to the SHA1 of the blob TPM_DIGEST DMI_measurement; // Correct measurement of the owning DMI } VTPM_DMI_RESOURCE; @@ -138,7 +143,7 @@ TPM_RESULT VTPM_SaveManagerData(void); TPM_RESULT VTPM_SaveManagerData(void); TPM_RESULT VTPM_LoadManagerData(void); -TPM_RESULT VTPM_New_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res); +TPM_RESULT VTPM_New_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res, BYTE startup_mode); TPM_RESULT VTPM_Close_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res); diff -r 18587d3e94c8 -r 8589cdd09636 tools/vtpm_manager/manager/vtsp.c --- a/tools/vtpm_manager/manager/vtsp.c Tue Jun 27 11:14:19 2006 +0100 +++ b/tools/vtpm_manager/manager/vtsp.c Tue Jun 27 11:15:48 2006 +0100 @@ -971,6 +971,17 @@ TPM_RESULT VTSP_Unseal(const TCS_CONTEXT return status; } +TPM_RESULT VTSP_SaveState( const TCS_CONTEXT_HANDLE hContext) { + + vtpmloginfo(VTPM_LOG_VTSP, "Calling TPM_SaveState.\n"); + + TPM_RESULT status = TPM_SUCCESS; + + // Call TCS + return ( TCSP_SaveState ( hContext ) ); + +} + // Function Reaches into unsupported TCS command, beware. TPM_RESULT VTSP_RawTransmit(const TCS_CONTEXT_HANDLE hContext, diff -r 18587d3e94c8 -r 8589cdd09636 tools/vtpm_manager/manager/vtsp.h --- a/tools/vtpm_manager/manager/vtsp.h Tue Jun 27 11:14:19 2006 +0100 +++ b/tools/vtpm_manager/manager/vtsp.h Tue Jun 27 11:15:48 2006 +0100 @@ -118,4 +118,6 @@ TPM_RESULT VTSP_Unseal(const TCS_CONTEXT TCS_AUTH *auth, TCS_AUTH *dataAuth); +TPM_RESULT VTSP_SaveState( const TCS_CONTEXT_HANDLE hContext); + #endif //_VTSP_H_ diff -r 18587d3e94c8 -r 8589cdd09636 tools/vtpm_manager/tcs/tcs.c --- a/tools/vtpm_manager/tcs/tcs.c Tue Jun 27 11:14:19 2006 +0100 +++ b/tools/vtpm_manager/tcs/tcs.c Tue Jun 27 11:15:48 2006 +0100 @@ -1126,6 +1126,49 @@ TPM_RESULT TCSP_ReadPubek(TCS_CONTEXT_HA return(returnCode); } + +TPM_RESULT TCSP_SaveState(TCS_CONTEXT_HANDLE hContext) // in +{ + // setup input/output parameters block + TPM_TAG tag = TPM_TAG_RQU_COMMAND; + UINT32 paramSize = 0; + TPM_COMMAND_CODE ordinal = TPM_ORD_SaveState; + TPM_RESULT returnCode = TPM_SUCCESS; + + // setup the TPM driver input and output buffers + TDDL_RESULT hRes = TDDL_E_FAIL; + TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH; + TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH; + + // Convert Byte Input parameter in the input byte stream InBuf + InLength = BSG_PackList(InBuf, 3, + BSG_TPM_TAG, &tag, + BSG_TYPE_UINT32, ¶mSize, + BSG_TPM_COMMAND_CODE, &ordinal); + // fill paramSize again as we now have the correct size + BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2); + + vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength); + + // call the TPM driver + if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) == TDDL_SUCCESS) { + // unpack OutBuf to get the tag, paramSize, & returnCode + BSG_UnpackList(OutBuf, 3, + BSG_TPM_TAG, &tag, + BSG_TYPE_UINT32, ¶mSize, + BSG_TPM_COMMAND_CODE, &returnCode); + + if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) { + vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize); + } else { + vtpmlogerror(VTPM_LOG_TCS, "TCSP_SaveState Failed with return code %s\n", tpm_get_error_name(returnCode)); + } + } + + return(returnCode); +} + + TPM_RESULT TCSP_RawTransmitData( UINT32 inDataSize, // in BYTE *inData, // in UINT32 *outDataSize,// in/out diff -r 18587d3e94c8 -r 8589cdd09636 tools/vtpm_manager/tcs/tcs.h --- a/tools/vtpm_manager/tcs/tcs.h Tue Jun 27 11:14:19 2006 +0100 +++ b/tools/vtpm_manager/tcs/tcs.h Tue Jun 27 11:15:48 2006 +0100 @@ -229,7 +229,10 @@ TPM_RESULT TCSP_ReadPubek ( TCS_CONTEXT ); -// Non-Standard TCSP call to give direct access to TransmitData. +// Non-Standard TCSP calls +TPM_RESULT TCSP_SaveState(TCS_CONTEXT_HANDLE hContext); // in + +//Give direct access to TransmitData. // Key and Auth Management is done before transfering command to TDDL. TPM_RESULT TCSP_RawTransmitData(UINT32 inDataSize, // in BYTE *inData, // in diff -r 18587d3e94c8 -r 8589cdd09636 tools/vtpm_manager/util/tcg.h --- a/tools/vtpm_manager/util/tcg.h Tue Jun 27 11:14:19 2006 +0100 +++ b/tools/vtpm_manager/util/tcg.h Tue Jun 27 11:15:48 2006 +0100 @@ -389,6 +389,11 @@ typedef struct pack_constbuf_t { #define TPM_DELEGATE_ADMIN TPM_BASE + 77 // Delegation table management not enabled #define TPM_TRANSPORT_EXCLUSIVE TPM_BASE + 78 // There was a command executed outside of an exclusive transport session +// TPM_STARTUP_TYPE values +#define TPM_ST_CLEAR 0x0001 +#define TPM_ST_STATE 0x0002 +#define TPM_ST_DEACTIVATED 0x003 + // TPM_TAG values #define TPM_TAG_RQU_COMMAND 0x00c1 #define TPM_TAG_RQU_AUTH1_COMMAND 0x00c2 diff -r 18587d3e94c8 -r 8589cdd09636 tools/examples/vtpm-impl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/examples/vtpm-impl Tue Jun 27 11:15:48 2006 +0100 @@ -0,0 +1,136 @@ +#!/bin/bash +# =================================================================== +# +# Copyright (c) 2005, Intel Corp. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +# OF THE POSSIBILITY OF SUCH DAMAGE. +# =================================================================== + +VTPM_IMPL_DEFINED=1 + +# | SRC | TAG | CMD SIZE | ORD | type| mode +TPM_CMD_OPEN=\\x00\\x00\\x00\\x00\\x01\\xc1\\x00\\x00\\x00\\x10\\x01\\x00\\x00\\x01\\x01\\x01 +TPM_CMD_RESM=\\x00\\x00\\x00\\x00\\x01\\xc1\\x00\\x00\\x00\\x10\\x01\\x00\\x00\\x01\\x01\\x02 +TPM_CMD_CLOS=\\x00\\x00\\x00\\x00\\x01\\xc1\\x00\\x00\\x00\\x0e\\x01\\x00\\x00\\x02 +TPM_CMD_DELE=\\x00\\x00\\x00\\x00\\x01\\xc1\\x00\\x00\\x00\\x0e\\x01\\x00\\x00\\x03 + +TPM_SUCCESS=00000000 + +TX_VTPM_MANAGER=/var/vtpm/fifos/from_console.fifo +RX_VTPM_MANAGER=/var/vtpm/fifos/to_console.fifo + +# -------------------- Helpers for binary streams ----------- + +function str_to_hex32() { + printf "%0.8x" $1 +} + +function hex32_to_bin() { + local inst=$(str_to_hex32 $1); + + local n1=`echo $inst | sed 's/\(..\)....../\\\\x\1/'` + local n2=`echo $inst | sed 's/..\(..\)..../\\\\x\1/'` + local n3=`echo $inst | sed 's/....\(..\)../\\\\x\1/'` + local n4=`echo $inst | sed 's/......\(..\)/\\\\x\1/'` + + echo "$n1$n2$n3$n4" +} + +function vtpm_manager_cmd() { + local cmd=$1; + local inst=$2; + local inst_bin=$(hex32_to_bin $inst); + + #send cmd to vtpm_manager + printf "$cmd$inst_bin" > $TX_VTPM_MANAGER + + #recv response + local resp_hex=`dd skip=10 bs=1 count=4 if=$RX_VTPM_MANAGER 2> /dev/null | xxd -ps` + + #return whether the command was successful + if [ $resp_hex != $TPM_SUCCESS ]; then + vtpm_fatal_error=1 + false + else + true + fi +} + +# ------------------ Command handlers ----------------- + +# Create new vtpm instance & set it up for use +function vtpm_create () { + # Creation is handled implicitly by the manager on first setup + # so just set it up for use + $(vtpm_start $1) +} + +# Setup vtpm instance for use. +function vtpm_start() { + $(vtpm_manager_cmd $TPM_CMD_OPEN $1) +} + +function vtpm_resume() { + $(vtpm_manager_cmd $TPM_CMD_RESM $1) +} + +# Reset the vtpm AKA clear PCRs +function vtpm_reset() { + #not used by current implemenation + true +} + +# Shutdown the vtpm while the vm is down +# This could be a suspend of shutdown +# we cannot distinquish, so save the state +# and decide on startup if we should keep is +function vtpm_suspend() { + $(vtpm_manager_cmd $TPM_CMD_CLOS $1) +} + + +function vtpm_delete() { + local inst=$1 + if $(vtpm_manager_cmd $TPM_CMD_DELE $inst); then + rm -f /var/vtpm/vtpm_dm_$1.data + true + else + vtpm_fatal_error=1 + false + fi +} + +function vtpm_migrate() { + echo "Error: vTPM migration accross machines not implemented." +} + +function vtpm_migrate_recover() { + true +} + _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |