*-----------------------------------------------------------------------------*/
#include "teec_connection.h"
#include <tee_internal_api.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdint.h>
#include <sys/stat.h>
+#include <sys/mman.h>
/*-----------------------------------------------------------------------------
* MACROS
#define PAGE_SIZE 0x1000
#define PAGE_MASK (~(PAGE_SIZE - 1))
-#define MAX_ID 64U
+#define SHM_MAX_ID INT32_MAX
+#define SHM_NAME_TEMPLATE "/teec_shm%d"
/*-----------------------------------------------------------------------------
* Globals
*-----------------------------------------------------------------------------*/
typedef struct smem_info {
int32_t memKey;
- uint32_t ftokID;
- uint32_t pathID;
} mem_info;
typedef struct sTEEC_ContextList {
TEEC_Context *context;
} TEEC_ContextList;
-typedef struct sMemkeyList {
- LIST_ENTRY(sMemkeyList) mem_list;
- mem_info *mem;
-} MemkeyList;
-
LIST_HEAD(context_listhead, sTEEC_ContextList) context_list = LIST_HEAD_INITIALIZER(NULL);
-LIST_HEAD(memkey_listhead, sMemkeyList) memkey_list = LIST_HEAD_INITIALIZER(NULL);
-
-uint32_t ftokId = 0;
-uint32_t pathId = 0;
-
-static pthread_rwlock_t key_lock = PTHREAD_RWLOCK_INITIALIZER;
static pthread_rwlock_t context_list_lock = PTHREAD_RWLOCK_INITIALIZER;
-static pthread_rwlock_t memkey_list_lock = PTHREAD_RWLOCK_INITIALIZER;
-static pthread_rwlock_t file_create_lock = PTHREAD_RWLOCK_INITIALIZER;
-
/*-----------------------------------------------------------------------------
* Local functions
*-----------------------------------------------------------------------------*/
/*
* === FUNCTION ======================================================================
- * Name: initShm
- * Description: Local function to create shm pathname file
- * Parameters: path - pathname
- * Return: 0 on success
- * -1 on failure
+ * Name: alignSize
+ * Description: Local function to compute aligned size
+ * Parameters: size - the size
+ * Return: a size aligned to the page size
* =====================================================================================
*/
-static int32_t initShm(char* path) {
- LOGD(TEEC_LIB, "Entry");
- int fd;
- struct stat attr;
- snprintf(path, 20, "/tmp/shm%d", pathId);
-
- pthread_rwlock_wrlock(&file_create_lock);
- if (stat(path, &attr) == -1) {
- // FIXME increased permission level (was S_IRWXU only)
- fd = creat(path, S_IRWXU | S_IRWXG | S_IRWXO);
- if (-1 == fd) {
- LOGE(TEEC_LIB, "shm file creation failed");
- return -1;
- }
- close(fd);
+static uint32_t alignSize(uint32_t size)
+{
+ uint32_t retSize = size;
+
+ if (retSize < PAGE_SIZE) {
+ retSize = PAGE_SIZE;
+ } else if (retSize & (PAGE_SIZE - 1)) {
+ retSize = (retSize & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
}
- pthread_rwlock_unlock(&file_create_lock);
- return 0;
-}
-/*
- * === FUNCTION ======================================================================
- * Name: checkMemory
- * Description: Local function to check if the Memory is already in use
- * Parameters: None
- * Return: 0 on success
- * -1 on failure
- * =====================================================================================
- */
-static int32_t checkMemory(void) {
- LOGD(TEEC_LIB, "Entry");
- uint32_t found = 0;
- MemkeyList *pmem_info;
+ retSize = (retSize + (PAGE_SIZE - 1)) & PAGE_MASK;
- /* Check if the memory is in the memory list containing all the allocated
- * shared memory info
- */
- pthread_rwlock_wrlock(&memkey_list_lock);
- LIST_FOREACH(pmem_info, &memkey_list, mem_list)
- {
- if ((pmem_info->mem->ftokID == ftokId) && (pmem_info->mem->pathID == pathId)) {
- found = 1;
- break;
- }
- }
- pthread_rwlock_unlock(&memkey_list_lock);
- return found;
+ return retSize;
}
/*
static int32_t allocateSharedMemory(TEEC_SharedMemory *shm) {
LOGD(TEEC_LIB, "Entry");
TEEC_SharedMemoryImp* sharedMem_imp = (TEEC_SharedMemoryImp*)shm->imp;
- int32_t memKey = -1;
+ int32_t memKey = 0;
uint32_t size = shm->size;
- int32_t shmid = -1;
- char path[20];
- uint32_t pathIdBase = pathId;
- uint32_t ftokIdBase = ftokId;
- MemkeyList *pmem_info = NULL;
-
- pthread_rwlock_wrlock(&key_lock);
- // Get shared memory key to be shared with TEEStub
+ char shm_name[NAME_MAX];
+ int fd_shm = -1;
+ int res;
+
+ mode_t origMask = umask(0);
+
do {
- ftokId = (ftokId % MAX_ID) + 1;
- if (1 == ftokId) {
- pathId = (pathId % MAX_ID) + 1;
- if (-1 == initShm(path)) {
- LOGE(TEEC_LIB, "initShm failed");
- return TEEC_ERROR_GENERIC;
- }
- } else {
- snprintf(path, 20, "/tmp/shm%d", pathId);
+ res = snprintf(shm_name, sizeof(shm_name), SHM_NAME_TEMPLATE, memKey);
+ if (res == sizeof(shm_name)) {
+ umask(origMask);
+ LOGE(TEEC_LIB, "the shm object name is too long");
+ return TEEC_ERROR_GENERIC;
}
- } while((checkMemory()) && (pathIdBase != pathId) && (ftokIdBase != ftokId));
- if (checkMemory()) {
- LOGE(TEEC_LIB, "All memory segments already in use");
- return TEEC_ERROR_OUT_OF_MEMORY;
- }
+ fd_shm = shm_open(shm_name, O_RDWR | O_CREAT | O_EXCL, 0660);
+ if (fd_shm >= 0) {
+ break;
+ }
- if ((memKey = ftok(path, ftokId)) == -1) {
- perror("ftok: ftok failed");
- }
+ if (errno != EEXIST) {
+ umask(origMask);
+ LOGE(TEEC_LIB, "Cannot create shared memory object, error: %s", strerror(errno));
+ return TEEC_ERROR_GENERIC;
+ }
- pmem_info = (MemkeyList*)OsaMalloc(sizeof(MemkeyList));
- if (!pmem_info) {
- LOGE(TEEC_LIB, "pmem_info malloc failed");
- return TEEC_ERROR_OUT_OF_MEMORY;
- }
- pmem_info->mem = (mem_info*)OsaMalloc(sizeof(mem_info));
- if (!pmem_info->mem) {
- LOGE(TEEC_LIB, "pmem_info->mem malloc failed");
- OsaFree(pmem_info);
- return TEEC_ERROR_OUT_OF_MEMORY;
- }
+ memKey++;
+ } while (memKey < SHM_MAX_ID);
- pmem_info->mem->ftokID = ftokId;
- pmem_info->mem->pathID = pathId - 1;
- pthread_rwlock_unlock(&key_lock);
- // Check if the obtained Shared Memory Key is valid
- if (memKey == -1) {
- LOGE(TEEC_LIB, "ftok failed");
- OsaFree(pmem_info->mem);
- OsaFree(pmem_info);
+ umask(origMask);
+
+ if (memKey == SHM_MAX_ID) {
+ LOGE(TEEC_LIB, "Cannot find free shared memory slot");
return TEEC_ERROR_GENERIC;
}
- /* Allocate page aligned buffer */
- if (size < PAGE_SIZE) {
- size = PAGE_SIZE;
- } else if (size & (PAGE_SIZE - 1)) {
- size = (size & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
- }
- size = (size + (PAGE_SIZE - 1)) & PAGE_MASK;
- // Get the shared memory ID
- if ((shmid = shmget(memKey, size, IPC_CREAT | 0666)) == -1) {
- perror("shmget: shmget failed");
- }
- // Check if the obtained Shared Memory ID is valid
- if (shmid == -1) {
- LOGE(TEEC_LIB, "shmget failed");
- OsaFree(pmem_info->mem);
- OsaFree(pmem_info);
- return TEEC_ERROR_GENERIC;
+ size = alignSize(size);
+
+ if (ftruncate(fd_shm, size) == -1) {
+ close(fd_shm);
+ shm_unlink(shm_name);
+ LOGE(TEEC_LIB, "ftruncate failed, error: %s", strerror(errno));
+ return TEEC_ERROR_OUT_OF_MEMORY;
}
- // attach a buffer with the obtained shared memory ID
- shm->buffer = (void*)shmat(shmid, NULL, 0);
- // Check if the obtained buffer is valid
- if (!shm->buffer) {
- LOGE(TEEC_LIB, "shmat failed - allocateSharedMemory failed");
- OsaFree(pmem_info->mem);
- OsaFree(pmem_info);
- return TEEC_ERROR_GENERIC;
+ shm->buffer = (void *) mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_shm, 0);
+ if (shm->buffer == MAP_FAILED) {
+ close(fd_shm);
+ shm_unlink(shm_name);
+ LOGE(TEEC_LIB, "shmat failed, error: %s", strerror(errno));
+ return TEEC_ERROR_OUT_OF_MEMORY;
}
- // Clear the buffer
- memset(shm->buffer, 0x00, shm->size);
+ close(fd_shm);
- // Add the mem in the mem list
- pmem_info->mem->memKey = memKey;
- pthread_rwlock_wrlock(&memkey_list_lock);
- LIST_INSERT_HEAD(&memkey_list, pmem_info, mem_list);
- pthread_rwlock_unlock(&memkey_list_lock);
+ memset(shm->buffer, 0x00, shm->size);
// Update shared memory imp structure
sharedMem_imp->shmKey = memKey;
- sharedMem_imp->memId = shmid;
+ sharedMem_imp->size = size;
sharedMem_imp->allocPtr = shm->buffer;
+
return TEEC_SUCCESS;
}
*/
static void freeSharedMemory(TEEC_SharedMemory *shm) {
LOGD(TEEC_LIB, "Entry");
- MemkeyList *pmem_info;
+ char shm_name[NAME_MAX];
+ int ret;
+
TEEC_SharedMemoryImp* sharedMem_imp = (TEEC_SharedMemoryImp*)shm->imp;
- // Detach the buffer atached with the Shared Memory ID
- if (shmdt(sharedMem_imp->allocPtr) == -1) {
- LOGE(TEEC_LIB, "freeSharedMemory failed");
+ if (munmap(sharedMem_imp->allocPtr, sharedMem_imp->size) == -1) {
+ LOGE(TEEC_LIB, "munmap failed, error: %s", strerror(errno));
+ return;
}
- sharedMem_imp->allocPtr = NULL;
- if ( -1 == shmctl( sharedMem_imp->memId, IPC_RMID, 0)) {
- LOGE(TEEC_LIB, "freeSharedMemory shmctl IPC_RMID failed");
+ ret = snprintf(shm_name, sizeof(shm_name), SHM_NAME_TEMPLATE, sharedMem_imp->shmKey);
+ if (ret == sizeof(shm_name)) {
+ LOGE(TEE_STUB, "the shm object name is too long");
+ return;
}
- sharedMem_imp->memId = -1;
- // Remove the memKey from the list
- pthread_rwlock_wrlock(&memkey_list_lock);
- LIST_FOREACH(pmem_info, &memkey_list, mem_list)
- {
- if (pmem_info->mem->memKey == sharedMem_imp->shmKey) {
- LIST_REMOVE(pmem_info, mem_list);
- OsaFree(pmem_info->mem);
- OsaFree(pmem_info);
- break;
- }
+
+ if (shm_unlink(shm_name) == -1) {
+ LOGE(TEE_STUB, "shm_unlink failed for %s, error: %s", shm_name, strerror(errno));
+ return;
}
- pthread_rwlock_unlock(&memkey_list_lock);
+ sharedMem_imp->allocPtr = NULL;
+ sharedMem_imp->shmKey = -1;
+ sharedMem_imp->size = 0;
}
/*
* Include files
*-----------------------------------------------------------------------------*/
#include "SharedMemoryMap.h"
-#include <sys/shm.h>
+
+#include <debug.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
#include <iostream>
+#include <stdint.h>
+#include <stdlib.h>
#include <string.h>
+#include <sys/shm.h>
+#include <sys/mman.h>
#include <time.h>
-#include <stdlib.h>
-#include <debug.h>
+#include <unistd.h>
+
using namespace std;
/*-----------------------------------------------------------------------------
#define PAGE_SIZE 0x1000
#define PAGE_MASK (~(PAGE_SIZE - 1))
+#define SHM_MAX_ID INT32_MAX
+#define SHM_NAME_PREFIX "/teec_shm"
+
map<uint32_t, registerItem> SharedMemoryMap::shmMap;
/*-----------------------------------------------------------------------------
* Member functions
*-----------------------------------------------------------------------------*/
+
+static uint32_t alignSize(uint32_t size)
+{
+ uint32_t retSize = size;
+
+ if (retSize < PAGE_SIZE) {
+ retSize = PAGE_SIZE;
+ } else if (retSize & (PAGE_SIZE - 1)) {
+ retSize = (retSize & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
+ }
+
+ retSize = (retSize + (PAGE_SIZE - 1)) & PAGE_MASK;
+
+ return retSize;
+}
+
/**
* Adds a key to a map
* @param key[in] Shared memory key
map<uint32_t, registerItem>::iterator it = shmMap.find(key);
if (it != shmMap.end()) {
registerItem item = it->second;
- if (-1 != shmdt(item.pBuffer)) {
- shmMap.erase(it);
- return true;
- } else return false;
+
+ if (item.internal) {
+ return false;
+ }
+
+ if (munmap(item.pBuffer, item.size) == -1) {
+ LOGE(TEE_STUB, "cannot munmap buffer %p, error: %s", item.pBuffer, strerror(errno));
+ return false;
+ }
+
+ shmMap.erase(it);
+ return true;
}
return false;
}
}
void* SharedMemoryMap::newOnceSharedMemory(uint32_t size) {
- static uint32_t add_value = 0;
- if(++add_value == 10000) add_value = 0;
- srand(time(NULL) + add_value + (uintptr_t)&size);
- uint32_t useKey = rand();
-
- //uint32_t useKey = (uint32_t)&size;
- while(isExist(useKey, 0))
- {
- LOGD(TEE_STUB, "Exist Key(%u)",useKey);
- useKey += 1;
- }
- LOGD(TEE_STUB, "Key for shm(size : %u) : %u", size, useKey);
+ int32_t memKey = 0;
+ int fd_shm = -1;
- bool sharedResult = true;
- uint32_t shmid = shmget(useKey, size, IPC_CREAT | 0666);
- if(shmid <= 0)
- {
- LOGE(TEE_STUB, "shmid failed(%d)",(int32_t)shmid);
- sharedResult = false;
- }
- /* Allocate page aligned buffer */
- if (size < PAGE_SIZE) {
- size = PAGE_SIZE;
- } else if (size & (PAGE_SIZE - 1)) {
- size = (size & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
- }
- size = (size + (PAGE_SIZE - 1)) & PAGE_MASK;
- void* buffer = (void*)shmat(shmid, NULL, 0);
- if (buffer == (void*)-1) {
- LOGE(TEE_STUB, "shmat failed(%p(shmid:%d))", buffer, shmid);
- sharedResult = false;
+ do {
+ std::string shm_name(SHM_NAME_PREFIX + std::to_string(memKey));
+
+ fd_shm = shm_open(shm_name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0660);
+ if (fd_shm >= 0) {
+ break;
+ }
+
+ if (errno != EEXIST) {
+ LOGE(TEE_STUB, "Cannot create shared memory object %s, error: %s",
+ shm_name.c_str(), strerror(errno));
+ return NULL;
+ }
+
+ memKey++;
+ } while (memKey < SHM_MAX_ID);
+
+ if (memKey == SHM_MAX_ID) {
+ LOGE(TEE_STUB, "Cannot find free shared memory slot");
+ return NULL;
}
- if (!buffer) {
- LOGE(TEE_STUB, "allocate failed");
- sharedResult = false;
+
+ size = alignSize(size);
+
+ if (ftruncate(fd_shm, size) == -1) {
+ close(fd_shm);
+ LOGE(TEE_STUB, "ftruncate failed, error: %s", strerror(errno));
+ return NULL;
}
- if(sharedResult != false) {
- registerItem item;
- item.pBuffer = buffer;
- item.size = size;
- // Add shared memory allocated to shared memory map so that
- // it can be detached on closing the sessions or exiting the TA
- SharedMemoryMap::addToMap(useKey, &item);
- LOGD(TEE_STUB, "newOnceSharedMemory return %p(size:%u)", buffer, size);
- return buffer;
+ void *buffer = (void *) mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_shm, 0);
+ if (buffer == NULL) {
+ close(fd_shm);
+ LOGE(TEE_STUB, "newOnceSharedMemory mmap failed, size: %u error: %s",
+ size, strerror(errno));
+ return NULL;
}
- LOGE(TEE_STUB, "newOnceSharedMemory return NULL");
- return 0;
+
+ close(fd_shm);
+
+ registerItem item;
+ item.pBuffer = buffer;
+ item.size = size;
+ item.internal = true;
+ // Add shared memory allocated to shared memory map so that
+ // it can be detached on closing the sessions or exiting the TA
+ SharedMemoryMap::addToMap(memKey, &item);
+ LOGD(TEE_STUB, "newOnceSharedMemory return %p(size:%u)", buffer, size);
+ return buffer;
}
bool SharedMemoryMap::deleteOnceSharedMemory(void* buffer) {
it++) {
registerItem item = it->second;
if(buffer == item.pBuffer) {
- if (-1 != shmdt(item.pBuffer)) {
- LOGD(TEE_STUB, "deleteOnceSharedMemory return true(%p(%u))",item.pBuffer, item.size);
- shmMap.erase(it);
- return true;
- } else {
- LOGE(TEE_STUB, "deleteOnceSharedMemory return false(shmdt return fail %p)", buffer);
+
+ if (!item.internal) {
return false;
}
+
+ std::string shm_name(SHM_NAME_PREFIX + std::to_string(it->first));
+
+ if (munmap(item.pBuffer, item.size) == -1) {
+ LOGE(TEE_STUB, "can not find munmap buffer %p, error: %s",
+ buffer, strerror(errno));
+ return false;
+ }
+
+ if (shm_unlink(shm_name.c_str()) == -1) {
+ LOGE(TEE_STUB, "cannot shm_unlink %s, error: %s",
+ shm_name.c_str(), strerror(errno));
+ return false;
+ }
+
+ shmMap.erase(it);
+
+ return true;
}
}
- LOGE(TEE_STUB, "deleteOnceSharedMemory return false(can not find %p)", buffer);
+
+ LOGE(TEE_STUB, "deleteOnceSharedMemory failed (cannot find %p)", buffer);
return false;
}
* @return true if shared memory was successfully created else false.
*/
bool SharedMemoryMap::allocateSharedMemory(Operation &op) {
- bool sharedResult = true;
for (int i = 0; i < 4; i++) {
uint32_t type = ((op.paramTypes) >> (8 * i)) & 0x7f;
// If not of value type, then has to be of memory reference type.
}
else
{
- uint32_t shmid = shmget(op.shmID[i], size, 0666);
- /* Allocate page aligned buffer */
- if (size < PAGE_SIZE) {
- size = PAGE_SIZE;
- } else if (size & (PAGE_SIZE - 1)) {
- size = (size & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
+ std::string shm_name(SHM_NAME_PREFIX + std::to_string(op.shmID[i]));
+
+ int fd_shm = shm_open(shm_name.c_str(), O_RDWR, 0);
+ if (fd_shm == -1) {
+ LOGE(TEE_STUB, "shm_open %s failed, error: %s", shm_name.c_str(), strerror(errno));
+ return false;
}
- size = (size + (PAGE_SIZE - 1)) & PAGE_MASK;
- op.params[i].memref.buffer = (void*)shmat(shmid, NULL, 0);
- if (op.params[i].memref.buffer == (void*)-1) {
- LOGE(TEE_STUB, "shmat failed");
- sharedResult = false;
+
+ size = alignSize(size);
+
+ op.params[i].memref.buffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_shm, 0);
+
+ close(fd_shm);
+
+ if (op.params[i].memref.buffer == MAP_FAILED) {
+ LOGE(TEE_STUB, "allocateSharedMemory mmap failed, size: %u error: %s",
+ size, strerror(errno));
+ return false;
}
+
if (!op.params[i].memref.buffer) {
- LOGE(TEE_STUB, "allocate failed");
- sharedResult = false;
+ LOGE(TEE_STUB, "allocate failed, the buffer is NULL");
+ return false;
}
- if(sharedResult != false) {
- registerItem item;
- item.pBuffer = op.params[i].memref.buffer;
- item.size = size;
- op.params[i].memref.buffer =
- (void*)(((char*)op.params[i].memref.buffer) + offset);
- // Add shared memory allocated to shared memory map so that
- // it can be detached on closing the sessions or exiting the TA
- SharedMemoryMap::addToMap(op.shmID[i], &item);
- }
+ registerItem item;
+ item.pBuffer = op.params[i].memref.buffer;
+ item.size = size;
+ item.internal = false;
+ op.params[i].memref.buffer =
+ (void*)(((char*)op.params[i].memref.buffer) + offset);
+ // Add shared memory allocated to shared memory map so that
+ // it can be detached on closing the sessions or exiting the TA
+ SharedMemoryMap::addToMap(op.shmID[i], &item);
}
}
}
- return sharedResult;
+ return true;
}
/**