aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuden <luden@ghostmail.com>2016-03-09 22:14:28 +0100
committerZiyan <jaraidaniel@gmail.com>2016-04-03 14:56:10 +0200
commit51bcade11201207a7cf1ccc7aedae03c6ec20d37 (patch)
treedb5fa49120e789e486a3ea4a6cc624f539d3c53e
parentf02ae7cd80cf786b23761f8b99dec5c2c670fbd6 (diff)
downloadkernel_samsung_tuna-51bcade11201207a7cf1ccc7aedae03c6ec20d37.zip
kernel_samsung_tuna-51bcade11201207a7cf1ccc7aedae03c6ec20d37.tar.gz
kernel_samsung_tuna-51bcade11201207a7cf1ccc7aedae03c6ec20d37.tar.bz2
tuna-compatible version of SMC PA protocol.
The only publicly-available version of SMC PA firmware for tuna uses older communication protocol between the "normal world" and "secure world". This change downgrades the communication parts of the protocol without touching the other parts of the stack. While in theory this could lead to the incompatibilities in the other parts of the code due to versions mismatch, things seem to work fine in my limited testing + this keeps in place bug-fixes that are present in later version of the code + there are less things to modify compared to the downgrade of the complete SMC-related code base.
-rw-r--r--security/smc/Kconfig2
-rw-r--r--security/smc/bridge_pub2sec.S12
-rw-r--r--security/smc/tf_comm_mshield.c124
-rw-r--r--security/smc/tf_defs.h15
-rw-r--r--security/smc/tf_device_mshield.c36
-rw-r--r--security/smc/tf_protocol.h16
-rw-r--r--security/smc/tf_zebra.h2
7 files changed, 112 insertions, 95 deletions
diff --git a/security/smc/Kconfig b/security/smc/Kconfig
index 9e0a8aa..5ba27e1 100644
--- a/security/smc/Kconfig
+++ b/security/smc/Kconfig
@@ -3,7 +3,7 @@ config TF_ZEBRA
config TF_CRYPTO_RNG
tristate "Use OMAP4 HW RNG"
- depends on ARCH_OMAP4 && m
+ depends on ARCH_OMAP4
select SECURITY_MIDDLEWARE_COMPONENT
default n
help
diff --git a/security/smc/bridge_pub2sec.S b/security/smc/bridge_pub2sec.S
index 1c9df24..224be98 100644
--- a/security/smc/bridge_pub2sec.S
+++ b/security/smc/bridge_pub2sec.S
@@ -63,12 +63,8 @@ schedule_secure_world:
b label_smc
return_from_rpc:
- /* Always return success to an RPC */
- /* The effective status is stored in the L1 shared buffer */
- mov r0, #0x00000000
- mov r1, #0x00000000
- mov r2, #0x00000000
- mov r3, #0x00000000
+ ldr r9, =g_RPC_parameters
+ ldm r9, {r0-r3}
/* fall through... */
return_from_irq:
@@ -109,8 +105,8 @@ rpc_handler:
mov r9, #RPC_ADVANCEMENT_PENDING
str r9, [r8]
- /* The effective command is stored in the L1 shared buffer */
- mov r0, #0x00000000
+ ldr r8, =g_RPC_parameters
+ stm r8, {r0-r3}
ldr r8, =g_secure_task_id
str r6, [r8]
diff --git a/security/smc/tf_comm_mshield.c b/security/smc/tf_comm_mshield.c
index 5d3bd26..23b6203 100644
--- a/security/smc/tf_comm_mshield.c
+++ b/security/smc/tf_comm_mshield.c
@@ -69,6 +69,7 @@
#define RPC_ADVANCEMENT_FINISHED 2
u32 g_RPC_advancement;
+u32 g_RPC_parameters[4] = {0, 0, 0, 0};
u32 g_secure_task_id;
u32 g_service_end;
@@ -342,14 +343,14 @@ int tf_schedule_secure_world(struct tf_comm *comm)
dpr_err("Service End ret=%X\n", ret);
if (ret == 0) {
- dmac_flush_range((void *)comm->l1_buffer,
- (void *)(((u32)(comm->l1_buffer)) +
+ dmac_flush_range((void *)comm->init_shared_buffer,
+ (void *)(((u32)(comm->init_shared_buffer)) +
PAGE_SIZE));
- outer_inv_range(__pa(comm->l1_buffer),
- __pa(comm->l1_buffer) +
+ outer_inv_range(__pa(comm->init_shared_buffer),
+ __pa(comm->init_shared_buffer) +
PAGE_SIZE);
- ret = comm->l1_buffer->exit_code;
+ ret = comm->init_shared_buffer->exit_code;
dpr_err("SMC PA failure ret=%X\n", ret);
if (ret == 0)
@@ -463,7 +464,12 @@ static u32 tf_rpc_init(struct tf_comm *comm)
spin_lock(&(comm->lock));
- protocol_version = comm->l1_buffer->protocol_version;
+ dmac_flush_range((void *)comm->init_shared_buffer,
+ (void *)(((u32)(comm->init_shared_buffer)) + PAGE_SIZE));
+ outer_inv_range(__pa(comm->init_shared_buffer),
+ __pa(comm->init_shared_buffer) + PAGE_SIZE);
+
+ protocol_version = comm->init_shared_buffer->protocol_version;
if ((GET_PROTOCOL_MAJOR_VERSION(protocol_version))
!= TF_S_PROTOCOL_MAJOR_VERSION) {
@@ -514,7 +520,7 @@ int tf_rpc_execute(struct tf_comm *comm)
/* Lock the RPC */
mutex_lock(&(comm->rpc_mutex));
- rpc_command = comm->l1_buffer->rpc_command;
+ rpc_command = g_RPC_parameters[1];
if (g_RPC_advancement == RPC_ADVANCEMENT_PENDING) {
dpr_info("%s: Executing CMD=0x%x\n",
@@ -525,21 +531,20 @@ int tf_rpc_execute(struct tf_comm *comm)
dpr_info("%s: RPC_CMD_YIELD\n", __func__);
rpc_error = RPC_YIELD;
- comm->l1_buffer->rpc_status = RPC_SUCCESS;
+ g_RPC_parameters[0] = RPC_SUCCESS;
break;
case RPC_CMD_TRACE:
rpc_error = RPC_NON_YIELD;
- comm->l1_buffer->rpc_status = tf_rpc_trace(comm);
+ g_RPC_parameters[0] = tf_rpc_trace(comm);
break;
default:
if (tf_crypto_execute_rpc(rpc_command,
comm->l1_buffer->rpc_cus_buffer) != 0)
- comm->l1_buffer->rpc_status =
- RPC_ERROR_BAD_PARAMETERS;
+ g_RPC_parameters[0] = RPC_ERROR_BAD_PARAMETERS;
else
- comm->l1_buffer->rpc_status = RPC_SUCCESS;
+ g_RPC_parameters[0] = RPC_SUCCESS;
rpc_error = RPC_NON_YIELD;
break;
}
@@ -641,6 +646,7 @@ int tf_init(struct tf_comm *comm)
spin_lock_init(&(comm->lock));
comm->flags = 0;
comm->l1_buffer = NULL;
+ comm->init_shared_buffer = NULL;
comm->se_initialized = false;
@@ -662,8 +668,9 @@ int tf_init(struct tf_comm *comm)
int tf_start(struct tf_comm *comm,
u32 workspace_addr, u32 workspace_size,
u8 *pa_buffer, u32 pa_size,
- u32 conf_descriptor, u32 conf_offset, u32 conf_size)
+ u8 *properties_buffer, u32 properties_length)
{
+ struct tf_init_buffer *init_shared_buffer = NULL;
struct tf_l1_shared_buffer *l1_shared_buffer = NULL;
struct tf_ns_pa_info pa_info;
int ret;
@@ -712,6 +719,18 @@ int tf_start(struct tf_comm *comm,
goto error1;
}
+ init_shared_buffer =
+ (struct tf_init_buffer *)
+ internal_get_zeroed_page(GFP_KERNEL);
+ if (init_shared_buffer == NULL) {
+ dpr_err("%s(%p): Ouf of memory!\n", __func__, comm);
+
+ ret = -ENOMEM;
+ goto error1;
+ }
+ /* Ensure the page is mapped */
+ __set_page_locked(virt_to_page(init_shared_buffer));
+
l1_shared_buffer =
(struct tf_l1_shared_buffer *)
internal_get_zeroed_page(GFP_KERNEL);
@@ -725,6 +744,9 @@ int tf_start(struct tf_comm *comm,
/* Ensure the page is mapped */
__set_page_locked(virt_to_page(l1_shared_buffer));
+ dpr_info("%s(%p): L0SharedBuffer={0x%08x, 0x%08x}\n",
+ __func__, comm,
+ (u32) init_shared_buffer, (u32) __pa(init_shared_buffer));
dpr_info("%s(%p): L1SharedBuffer={0x%08x, 0x%08x}\n",
__func__, comm,
(u32) l1_shared_buffer, (u32) __pa(l1_shared_buffer));
@@ -732,28 +754,57 @@ int tf_start(struct tf_comm *comm,
descr = tf_get_l2_descriptor_common((u32) l1_shared_buffer,
current->mm);
pa_info.certificate = (void *) workspace_addr;
- pa_info.parameters = (void *) __pa(l1_shared_buffer);
- pa_info.results = (void *) __pa(l1_shared_buffer);
+ pa_info.parameters = (void *) __pa(init_shared_buffer);
+ pa_info.results = (void *) __pa(init_shared_buffer);
+
+ init_shared_buffer->l1_shared_buffer_descr = (((u32) __pa(l1_shared_buffer) & 0xFFFFF000) | (descr & 0xFFF));
- l1_shared_buffer->l1_shared_buffer_descr = descr & 0xFFF;
+ init_shared_buffer->backing_store_addr = sdp_backing_store_addr;
+ init_shared_buffer->backext_storage_addr = sdp_bkext_store_addr;
+ init_shared_buffer->workspace_addr = workspace_addr;
+ init_shared_buffer->workspace_size = workspace_size;
- l1_shared_buffer->backing_store_addr = sdp_backing_store_addr;
- l1_shared_buffer->backext_storage_addr = sdp_bkext_store_addr;
- l1_shared_buffer->workspace_addr = workspace_addr;
- l1_shared_buffer->workspace_size = workspace_size;
+ init_shared_buffer->properties_length = properties_length;
+ if (properties_length == 0) {
+ init_shared_buffer->properties_buffer[0] = 0;
+ } else {
+ /* Test for overflow */
+ if ((init_shared_buffer->properties_buffer +
+ properties_length >
+ init_shared_buffer->properties_buffer) &&
+ (properties_length <=
+ init_shared_buffer->properties_length)) {
+ if (copy_from_user(init_shared_buffer->properties_buffer,
+ properties_buffer,
+ properties_length)) {
+ dpr_err("%s(%p): Failed to copy config buffer (%d, %d)\n",
+ __func__, comm,
+ (u32) properties_length, init_shared_buffer->properties_length);
+ ret = -EFAULT;
+ goto error1;
+ }
+ } else {
+ dpr_err("%s(%p): Configuration buffer size from userland is "
+ "incorrect(%d, %d)\n",
+ __func__, comm,
+ (u32) properties_length, init_shared_buffer->properties_length);
+ ret = -EFAULT;
+ goto error1;
+ }
+ }
dpr_info("%s(%p): System Configuration (%d bytes)\n",
- __func__, comm, conf_size);
+ __func__, comm, properties_length);
dpr_info("%s(%p): Starting PA (%d bytes)...\n",
__func__, comm, pa_size);
/*
* Make sure all data is visible to the secure world
*/
- dmac_flush_range((void *)l1_shared_buffer,
- (void *)(((u32)l1_shared_buffer) + PAGE_SIZE));
- outer_clean_range(__pa(l1_shared_buffer),
- __pa(l1_shared_buffer) + PAGE_SIZE);
+ dmac_flush_range((void *)init_shared_buffer,
+ (void *)(((u32)init_shared_buffer) + PAGE_SIZE));
+ outer_clean_range(__pa(init_shared_buffer),
+ __pa(init_shared_buffer) + PAGE_SIZE);
if (pa_size > workspace_size) {
dpr_err("%s(%p): PA size is incorrect (%x)\n",
@@ -782,11 +833,10 @@ int tf_start(struct tf_comm *comm,
wmb();
spin_lock(&(comm->lock));
+ comm->init_shared_buffer = init_shared_buffer;
comm->l1_buffer = l1_shared_buffer;
- comm->l1_buffer->conf_descriptor = conf_descriptor;
- comm->l1_buffer->conf_offset = conf_offset;
- comm->l1_buffer->conf_size = conf_size;
spin_unlock(&(comm->lock));
+ init_shared_buffer = NULL;
l1_shared_buffer = NULL;
/*
@@ -815,27 +865,27 @@ loop:
if (g_RPC_advancement == RPC_ADVANCEMENT_PENDING) {
dpr_info("%s: Executing CMD=0x%x\n",
- __func__, comm->l1_buffer->rpc_command);
+ __func__, g_RPC_parameters[1]);
- switch (comm->l1_buffer->rpc_command) {
+ switch (g_RPC_parameters[1]) {
case RPC_CMD_YIELD:
dpr_info("%s: RPC_CMD_YIELD\n", __func__);
set_bit(TF_COMM_FLAG_L1_SHARED_ALLOCATED,
&(comm->flags));
- comm->l1_buffer->rpc_status = RPC_SUCCESS;
+ g_RPC_parameters[0] = RPC_SUCCESS;
break;
case RPC_CMD_INIT:
dpr_info("%s: RPC_CMD_INIT\n", __func__);
- comm->l1_buffer->rpc_status = tf_rpc_init(comm);
+ g_RPC_parameters[0] = tf_rpc_init(comm);
break;
case RPC_CMD_TRACE:
- comm->l1_buffer->rpc_status = tf_rpc_trace(comm);
+ g_RPC_parameters[0] = tf_rpc_trace(comm);
break;
default:
- comm->l1_buffer->rpc_status = RPC_ERROR_BAD_PARAMETERS;
+ g_RPC_parameters[0] = RPC_ERROR_BAD_PARAMETERS;
break;
}
g_RPC_advancement = RPC_ADVANCEMENT_FINISHED;
@@ -867,10 +917,16 @@ error2:
spin_lock(&(comm->lock));
l1_shared_buffer = comm->l1_buffer;
+ init_shared_buffer = comm->init_shared_buffer;
comm->l1_buffer = NULL;
+ comm->init_shared_buffer = NULL;
spin_unlock(&(comm->lock));
error1:
+ if (init_shared_buffer != NULL) {
+ __clear_page_locked(virt_to_page(init_shared_buffer));
+ internal_free_page((unsigned long) init_shared_buffer);
+ }
if (l1_shared_buffer != NULL) {
__clear_page_locked(virt_to_page(l1_shared_buffer));
internal_free_page((unsigned long) l1_shared_buffer);
diff --git a/security/smc/tf_defs.h b/security/smc/tf_defs.h
index 9c28ed0..c630f6d 100644
--- a/security/smc/tf_defs.h
+++ b/security/smc/tf_defs.h
@@ -183,6 +183,18 @@ struct tf_shmem_desc {
/*----------------------------------------------------------------------------*/
+struct tf_init_buffer {
+ u32 exit_code;
+ u32 protocol_version;
+ u32 l1_shared_buffer_descr;
+ u32 backing_store_addr;
+ u32 backext_storage_addr;
+ u32 workspace_addr;
+ u32 workspace_size;
+ u32 properties_length;
+ u8 properties_buffer[1];
+};
+
/*
* This structure describes the communication with the Secure World
*
@@ -246,6 +258,9 @@ struct tf_comm {
*/
int se_initialized;
+ /* Virtual address of the L0 communication buffer */
+ struct tf_init_buffer *init_shared_buffer;
+
/*
* Lock to be held by a client when executing an RPC
*/
diff --git a/security/smc/tf_device_mshield.c b/security/smc/tf_device_mshield.c
index 614c71a..0bd30ad 100644
--- a/security/smc/tf_device_mshield.c
+++ b/security/smc/tf_device_mshield.c
@@ -137,10 +137,6 @@ static long tf_ctrl_device_ioctl(struct file *file, unsigned int ioctl_num,
switch (pa_ctrl.nPACommand) {
case TF_PA_CTRL_START: {
- struct tf_shmem_desc *shmem_desc = NULL;
- u32 shared_mem_descriptors[TF_MAX_COARSE_PAGES];
- u32 descriptor_count;
- u32 offset;
struct tf_connection *connection;
dpr_info("%s(%p): Start the SMC PA (%d bytes) with conf "
@@ -154,41 +150,12 @@ static long tf_ctrl_device_ioctl(struct file *file, unsigned int ioctl_num,
goto start_exit;
}
- result = tf_validate_shmem_and_flags(
- (u32)pa_ctrl.conf_buffer,
- pa_ctrl.conf_size,
- TF_SHMEM_TYPE_READ);
- if (result != 0)
- goto start_exit;
-
- offset = 0;
- result = tf_map_shmem(
- connection,
- (u32)pa_ctrl.conf_buffer,
- TF_SHMEM_TYPE_READ,
- true, /* in user space */
- shared_mem_descriptors,
- &offset,
- pa_ctrl.conf_size,
- &shmem_desc,
- &descriptor_count);
- if (result != 0)
- goto start_exit;
-
- if (descriptor_count > 1) {
- dpr_err("%s(%p): configuration file is too long (%d)\n",
- __func__, file, descriptor_count);
- result = -ENOMEM;
- goto start_exit;
- }
-
result = tf_start(&dev->sm,
dev->workspace_addr,
dev->workspace_size,
pa_ctrl.pa_buffer,
pa_ctrl.pa_size,
- shared_mem_descriptors[0],
- offset,
+ pa_ctrl.conf_buffer,
pa_ctrl.conf_size);
if (result)
dpr_err("SMC: start failed\n");
@@ -196,7 +163,6 @@ static long tf_ctrl_device_ioctl(struct file *file, unsigned int ioctl_num,
dpr_info("SMC: started\n");
start_exit:
- tf_unmap_shmem(connection, shmem_desc, true); /* full cleanup */
break;
}
diff --git a/security/smc/tf_protocol.h b/security/smc/tf_protocol.h
index cf9e68f..4984bfa 100644
--- a/security/smc/tf_protocol.h
+++ b/security/smc/tf_protocol.h
@@ -624,27 +624,11 @@ union tf_answer {
/* Structure of the Communication Buffer */
struct tf_l1_shared_buffer {
- #ifdef CONFIG_TF_ZEBRA
- u32 exit_code;
- u32 l1_shared_buffer_descr;
- u32 backing_store_addr;
- u32 backext_storage_addr;
- u32 workspace_addr;
- u32 workspace_size;
- u32 conf_descriptor;
- u32 conf_size;
- u32 conf_offset;
- u32 protocol_version;
- u32 rpc_command;
- u32 rpc_status;
- u8 reserved1[16];
- #else
u32 config_flag_s;
u32 w3b_size_max_s;
u32 reserved0;
u32 w3b_size_current_s;
u8 reserved1[48];
- #endif
u8 version_description[TF_DESCRIPTION_BUFFER_LENGTH];
u32 status_s;
u32 reserved2;
diff --git a/security/smc/tf_zebra.h b/security/smc/tf_zebra.h
index e67e95b..ae41ed4 100644
--- a/security/smc/tf_zebra.h
+++ b/security/smc/tf_zebra.h
@@ -32,7 +32,7 @@ int tf_ctrl_device_register(void);
int tf_start(struct tf_comm *comm,
u32 workspace_addr, u32 workspace_size,
u8 *pa_buffer, u32 pa_size,
- u32 conf_descriptor, u32 conf_offset, u32 conf_size);
+ u8 *properties_buffer, u32 properties_length);
/* Assembler entry points to/from secure */
u32 schedule_secure_world(u32 app_id, u32 proc_id, u32 flags, u32 args);