Refactory of the proxy stubs code.

Added the IOBlks proxystub.
Included reliance edge test.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@12020 110e8d01-0319-4d1e-a829-52ad28d1bb01
This commit is contained in:
isiora 2018-05-11 09:56:36 +00:00
parent fe8665fe9e
commit dd882e357e
8 changed files with 729 additions and 244 deletions

View File

@ -38,16 +38,43 @@
#define SKEL_REQ_PUTRES 3
#define SKEL_REQ_READY 4
#define STUB_OP_SOCKET 0
#define STUB_OP_CLOSE 1
#define STUB_OP_CONNECT 2
#define STUB_OP_RECV 3
#define STUB_OP_SEND 4
#define STUB_OP_SELECT 5
#define STUB_OP_BIND 6
#define STUB_OP_LISTEN 7
/* Sockets stub defines.*/
#define SOCK_OP_SOCKET 0
#define SOCK_OP_CLOSE 1
#define SOCK_OP_CONNECT 2
#define SOCK_OP_RECV 3
#define SOCK_OP_SEND 4
#define SOCK_OP_SELECT 5
#define SOCK_OP_BIND 6
#define SOCK_OP_LISTEN 7
#define EVT_F_SOCK_NEW_OP 1
/* Socket new op event.*/
#define EVT_F_SOCK_NEW_OP 1
/* Sockets stub service name.*/
#define SOCKS_SVC_NAME "TsSocksStubService"
/* IOBlocks stub defines.*/
#define IOBLKS_OP_OPEN 0
#define IOBLKS_OP_CLOSE 1
#define IOBLKS_OP_READ 2
#define IOBLKS_OP_WRITE 3
#define IOBLKS_OP_FLUSH 4
/* IOBlock new op event.*/
#define EVT_F_IOBLK_NEW_OP 2
/* IOBlock stub service name.*/
#define IOBLKS_SVC_NAME "TsIOBlksStubService"
/* Sector size.*/
#define IOBLKS_SECT_SIZE 512U
/* Remote Partition size, in sectors.*/
#define IOBLKS_PART_SIZE 96256U
/* Remote partition offset, in sectors.*/
#define IOBLKS_PART_OFFS 952320U
/*===========================================================================*/
/* Module pre-compile time settings. */
@ -63,13 +90,16 @@
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
typedef struct skel_ctx skel_ctx_t;
typedef struct skel_req {
uint32_t req; /* getop, cpyprms, putres */
uint32_t stub_op;
uint32_t stub_op_code;
uint32_t stub_op_result;
uint32_t stub_op_p_sz[METHOD_MAX_PARAMS];
uint32_t stub_op_p[METHOD_MAX_PARAMS];
uint32_t req; /* getop, cpyprms, putres */
uint32_t stub_op;
uint32_t stub_op_code;
uint32_t stub_op_result;
uint32_t stub_op_p_sz[METHOD_MAX_PARAMS];
uint32_t stub_op_p[METHOD_MAX_PARAMS];
skel_ctx_t *scp; /* the skeleton context this req come from.*/
} skel_req_t;
/*===========================================================================*/

View File

@ -0,0 +1,174 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file tsioblksstub.c
* @brief IOBlks stub for trusted services implementing the
* Reliance Edge api.
*
*/
#include "ch.h"
#include "chobjfifos.h"
#include "chtssi.h"
#include "tsproxystubs.h"
#include "tsioblksstub.h"
#include <redfs.h>
#include <redvolume.h>
#include <string.h>
#include <ctype.h>
/*===========================================================================*/
/* Module local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Module exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local types. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local variables. */
/*===========================================================================*/
static stub_ctx_t stub_ctx;
const VOLCONF gaRedVolConf[REDCONF_VOLUME_COUNT] = {
{
512, /* ulSectorSize.*/
IOBLKS_PART_SIZE, /* ullSectorCount.*/
0U, /* ullSectorOffset.*/
false, /* fAtomicSectorWrite.*/
1024U, /* ulInodeCount.*/
2U, /* bBlockIoRetries.*/
""
}
};
/*===========================================================================*/
/* Module local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Module exported functions. */
/*===========================================================================*/
/**
* @brief The IOBlks stub service.
*/
THD_WORKING_AREA(waTsIOBlksStubsService, 1024);
THD_FUNCTION(TsIOBlksStubsService, tsstatep) {
stub_ctx.event_flag = EVT_F_IOBLK_NEW_OP;
TsStubService((ts_state_t *)tsstatep, &stub_ctx);
}
/**
* @name The IOBlks api, in the Reliance Edge fashion.
* @{
*/
/**
* @brief Open the block device.
*/
REDSTATUS RedOsBDevOpen(uint8_t bVolNum, BDEVOPENMODE mode) {
(void)mode;
if (bVolNum != 0)
return -RED_EINVAL;
stub_op_t *op = getNewOp(&stub_ctx);
op->op_code = IOBLKS_OP_OPEN;
op->op_p[0].dir = OP_PRMDIR_NONE;
op->op_p[0].val = (uint32_t)bVolNum;
op->op_p[1].dir = OP_PRMDIR_NONE;
op->op_p[1].val = (uint32_t)mode;
return (REDSTATUS)callRemote(op);
}
/**
* @brief Close the block device.
*/
REDSTATUS RedOsBDevClose(uint8_t bVolNum) {
if (bVolNum != 0)
return -RED_EINVAL;
stub_op_t *op = getNewOp(&stub_ctx);
op->op_code = IOBLKS_OP_CLOSE;
op->op_p[0].dir = OP_PRMDIR_NONE;
op->op_p[0].val = (uint32_t)bVolNum;
return (REDSTATUS)callRemote(op);
}
/**
* @brief Read from the block device.
*/
REDSTATUS RedOsBDevRead(uint8_t bVolNum, uint64_t ullSectorStart, uint32_t ulSectorCount, void *pBuffer) {
if ((bVolNum != 0) ||
(ullSectorStart >= gaRedVolConf[bVolNum].ullSectorCount) ||
((gaRedVolConf[bVolNum].ullSectorCount - ullSectorStart) < ulSectorCount) ||
(pBuffer == NULL))
return -RED_EINVAL;
stub_op_t *op = getNewOp(&stub_ctx);
op->op_code = IOBLKS_OP_READ;
op->op_p[0].dir = OP_PRMDIR_NONE;
op->op_p[0].val = (uint32_t)bVolNum;
op->op_p[1].dir = OP_PRMDIR_NONE;
op->op_p[1].val = (uint32_t)ullSectorStart;
op->op_p[2].dir = OP_PRMDIR_NONE;
op->op_p[2].val = (uint32_t)ulSectorCount;
op->op_p[3].dir = OP_PRMDIR_OUT;
op->op_p[3].val = (uint32_t)pBuffer;
op->op_p[3].size = (uint32_t)(ulSectorCount * IOBLKS_SECT_SIZE);
return (int)callRemote(op);
}
/**
* @brief Write to the block device.
*/
REDSTATUS RedOsBDevWrite(uint8_t bVolNum, uint64_t ullSectorStart, uint32_t ulSectorCount, const void *pBuffer) {
if ((bVolNum != 0) ||
(ullSectorStart >= gaRedVolConf[bVolNum].ullSectorCount) ||
((gaRedVolConf[bVolNum].ullSectorCount - ullSectorStart) < ulSectorCount) ||
(pBuffer == NULL))
return -RED_EINVAL;
stub_op_t *op = getNewOp(&stub_ctx);
op->op_code = IOBLKS_OP_WRITE;
op->op_p[0].dir = OP_PRMDIR_NONE;
op->op_p[0].val = (uint32_t)bVolNum;
op->op_p[1].dir = OP_PRMDIR_NONE;
op->op_p[1].val = (uint32_t)ullSectorStart;
op->op_p[2].dir = OP_PRMDIR_NONE;
op->op_p[2].val = (uint32_t)ulSectorCount;
op->op_p[3].dir = OP_PRMDIR_IN;
op->op_p[3].val = (uint32_t)pBuffer;
op->op_p[3].size = (uint32_t)(ulSectorCount * IOBLKS_SECT_SIZE);
return (int)callRemote(op);
}
/**
* @brief Flush the block device.
*/
REDSTATUS RedOsBDevFlush(uint8_t bVolNum) {
if (bVolNum != 0)
return -RED_EINVAL;
stub_op_t *op = getNewOp(&stub_ctx);
op->op_code = IOBLKS_OP_FLUSH;
op->op_p[0].dir = OP_PRMDIR_NONE;
op->op_p[0].val = (uint32_t)bVolNum;
return (REDSTATUS)callRemote(op);
}
/** @} */

View File

@ -0,0 +1,68 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
This file is part of ChibiOS.
ChibiOS 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 3 of the License, or
(at your option) any later version.
ChibiOS 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, see <http://www.gnu.org/licenses/>.
*/
/**
* @file tsioblksstub.h
* @brief IOBlocks stub module macros and structures.
*
*/
#ifndef TSIOBLKSSTUB_H
#define TSIOBLKSSTUB_H
#include "ch.h"
#include "ccportab.h"
/*===========================================================================*/
/* Module constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Module pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Module macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
THD_FUNCTION(TsIOBlksStubsService, tsstatep);
extern THD_WORKING_AREA(waTsIOBlksStubsService, 1024);
#ifdef __cplusplus
}
#endif
/*===========================================================================*/
/* Module inline functions. */
/*===========================================================================*/
#endif /* TSIOBLKSSTUB_H */

View File

@ -0,0 +1,240 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file tssockstub.c
* @brief Sockets stub for trusted services.
*
*/
#include "ch.h"
#include "chobjfifos.h"
#include "chtssi.h"
#include "tsproxystubs.h"
#include <string.h>
#include <ctype.h>
/*===========================================================================*/
/* Module local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Module exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local types. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local variables. */
/*===========================================================================*/
static eventflags_t tsSkelIsReadyMask = 0;
/*===========================================================================*/
/* Module local functions. */
/*===========================================================================*/
static bool isOpValid(stub_ctx_t *scp, stub_op_t *op)
{
if ((op < &(scp->ops[0])) || (op >= &(scp->ops[STUB_MAX_OPS])))
return FALSE;
if (((char *)op - (char *)&(scp->ops[0])) % sizeof scp->ops[0])
return FALSE;
return TRUE;
}
/*===========================================================================*/
/* Module exported functions. */
/*===========================================================================*/
/**
* @brief Implement an a call to a NSEC function.
* @details It activates the channel between the stubs service and
* the skels daemon running in the nsec world.
* To do it, it uses an event to signal the corresponding skel
* daemon that a new op request is ready to be executed.
* Behind the scenes, the skel daemon will then gets the op, calling
* the stub service via smc. The daemon executes it and then calls
* the stub service again to post the result and to wake up the
* calling thread of this function.
*
* @param[in] op the 'remote' method description.
*
* @return the return value of 'remote' method.
*/
uint32_t callRemote(stub_op_t *op) {
uint32_t r;
chSysLock();
chFifoSendObjectI(&op->scp->ops_fifo, op);
chEvtBroadcastFlagsI(&tsEventSource, op->scp->event_flag);
chThdSuspendS(&op->op_wthdp);
op->op_state = FREE;
chSysUnlock();
r = op->op_code;
chFifoReturnObject(&op->scp->ops_fifo, op);
return r;
}
stub_op_t *getNewOp(stub_ctx_t *scp) {
stub_op_t *op = chFifoTakeObjectTimeout(&scp->ops_fifo, TIME_INFINITE);
memset(op, 0, sizeof *op);
op->op_state = CALLING;
op->scp = scp;
return op;
}
/**
* @brief The stubs service.
* @details And this is where the magic happens.
*/
void TsStubService(ts_state_t *svcp, stub_ctx_t *scp) {
skel_req_t *skrp;
stub_op_t *op;
msg_t r;
int i;
chFifoObjectInit(&scp->ops_fifo, sizeof (stub_op_t), STUB_MAX_OPS,
sizeof (uint8_t), scp->ops, scp->ops_msgs);
for (;/* ever */;) {
/* Wait a service request.*/
(void)tssiWaitRequest(svcp);
skrp = (skel_req_t *)TS_GET_DATA(svcp);
r = SMC_SVC_OK;
/* Process the request.*/
if (TS_GET_DATALEN(svcp) != sizeof (skel_req_t)) {
TS_SET_STATUS(svcp, SMC_SVC_INVALID);
continue;
}
switch (skrp->req) {
case SKEL_REQ_READY:
tsSkelIsReadyMask |= (eventflags_t)skrp->stub_op;
break;
case SKEL_REQ_GETOP:
/* The nsec skeleton calls us to get a new op ready to be executed.*/
if (chFifoReceiveObjectTimeout(&scp->ops_fifo, (void **)&op,
TIME_IMMEDIATE) == MSG_TIMEOUT) {
/* no op ready to be executed.*/
r = SMC_SVC_NHND;
break;
}
skrp->stub_op = (uint32_t)op;
skrp->stub_op_code = op->op_code;
/* Pass all the 'by value' arguments from stub to skel.*/
for (i = 0; i < METHOD_MAX_PARAMS; ++i) {
if (op->op_p[i].dir == OP_PRMDIR_NONE)
skrp->stub_op_p[i] = op->op_p[i].val;
}
op->op_state = PENDING;
break;
case SKEL_REQ_CPYPRMS:
/* The nsec skel calls us to get a copy of the 'in' parameters of
the specified op.
An 'in' parameter is an indirect argument, that is an argument
the value of which is a pointer to a memory buffer, that
must be copied in a non secure memory buffer.
It represents data to be consumed by the callee.*/
op = (stub_op_t *)skrp->stub_op;
if (!isOpValid(scp, op) || op->op_state != PENDING ||
op->op_code != skrp->stub_op_code) {
r = SMC_SVC_INVALID;
break;
}
/* Copy all 'in' parameters.
For each parameter check that the destination memory area
is in the non secure memory arena.*/
for (i = 0; i < METHOD_MAX_PARAMS; ++i) {
if ((op->op_p[i].dir & OP_PRMDIR_IN) == 0)
continue;
if (!tsIsAddrSpaceValid((void *)skrp->stub_op_p[i], op->op_p[i].size)) {
r = SMC_SVC_INVALID;
break;
}
memcpy((void *)skrp->stub_op_p[i], (void *)op->op_p[i].val,
op->op_p[i].size);
}
break;
case SKEL_REQ_PUTRES:
/* The nsec skel calls us to put a copy of the 'out' parameters of
the specified op.
An 'out' parameter is an indirect argument, that is an argument
the value of which is a pointer to a memory buffer, that
must be copied in a secure memory buffer.
It represents data produced by the callee.*/
op = (stub_op_t *)skrp->stub_op;
if (!isOpValid(scp, op) || op->op_state != PENDING ||
op->op_code != skrp->stub_op_code) {
r = SMC_SVC_INVALID;
break;
}
/* Copy all 'out' parameters.
For each parameter check that the source memory area
is in the non secure memory arena, and that the size returned
fits in the caller buffer size.*/
for (i = 0; i < METHOD_MAX_PARAMS; ++i) {
if ((op->op_p[i].dir & OP_PRMDIR_OUT) == 0)
continue;
if (!tsIsAddrSpaceValid((void *)skrp->stub_op_p[i], skrp->stub_op_p_sz[i])
|| (skrp->stub_op_p_sz[i] > op->op_p[i].size)) {
r = SMC_SVC_INVALID;
break;
}
memcpy((void *)op->op_p[i].val, (void *)skrp->stub_op_p[i],
skrp->stub_op_p_sz[i]);
}
if (r != SMC_SVC_OK)
break;
/* Set the return value of the 'remote' callee method,
and wake up the caller.*/
op->op_code = skrp->stub_op_result;
chThdResume(&op->op_wthdp, MSG_OK);
break;
default:
r = SMC_SVC_INVALID;
break;
}
/* Set the response.*/
TS_SET_STATUS(svcp, r);
}
}
/**
* @brief Is the skeletons daemon ready to operate?
* @details It is used at the startup to synchronize the
* stub service with the skeleton daemon.
*/
void tsWaitStubSkelReady(eventflags_t mask) {
while ((tsSkelIsReadyMask & mask) != mask) {
chThdSleepMilliseconds(100);
}
}

View File

@ -0,0 +1,102 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
This file is part of ChibiOS.
ChibiOS 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 3 of the License, or
(at your option) any later version.
ChibiOS 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, see <http://www.gnu.org/licenses/>.
*/
/**
* @file tsproxystubs.h
* @brief Proxy stubs module macros and structures.
*
*/
#ifndef TSPROXYSTUBS_H
#define TSPROXYSTUBS_H
#include "ch.h"
#include "ccportab.h"
#include "tscommon.h"
/*===========================================================================*/
/* Module constants. */
/*===========================================================================*/
#define METHOD_MAX_PARAMS 6
#define STUB_MAX_OPS 32
#define OP_PRMDIR_NONE 0
#define OP_PRMDIR_IN 1
#define OP_PRMDIR_OUT 2
/*===========================================================================*/
/* Module pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
typedef enum {FREE=0, CALLING, PENDING} op_state_t;
typedef struct stub_ctx stub_ctx_t;
typedef struct stub_param {
uint32_t dir;
uint32_t val;
uint32_t size;
} stub_parm_t;
typedef struct stub_op {
uint32_t op_code; /* the stub method op code.*/
op_state_t op_state; /* calling, pending, free.*/
stub_parm_t op_p[METHOD_MAX_PARAMS];
thread_reference_t op_wthdp; /* TS internal client thread (the caller).*/
stub_ctx_t *scp; /* the stub ctx this stub_op relates to.*/
} stub_op_t;
typedef struct stub_ctx {
eventflags_t event_flag;
objects_fifo_t ops_fifo;
msg_t ops_msgs[STUB_MAX_OPS];
stub_op_t ops[STUB_MAX_OPS];
} stub_ctx_t;
/*===========================================================================*/
/* Module macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void tsWaitStubSkelReady(eventflags_t mask);
void TsStubService(ts_state_t *svcp, stub_ctx_t *scp);
uint32_t callRemote(stub_op_t *op);
stub_op_t *getNewOp(stub_ctx_t *scp);
#ifdef __cplusplus
}
#endif
/*===========================================================================*/
/* Module inline functions. */
/*===========================================================================*/
#endif /* TSPROXYSTUBS_H */

View File

@ -0,0 +1,74 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
This file is part of ChibiOS.
ChibiOS 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 3 of the License, or
(at your option) any later version.
ChibiOS 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, see <http://www.gnu.org/licenses/>.
*/
/**
* @file tssockets.h
*/
#ifndef TSSOCKETS_H
#define TSSOCKETS_H
/*===========================================================================*/
/* Module constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Module pre-compile time settings. */
/*===========================================================================*/
#define socket ts_socket
#define connect ts_connect
#define send ts_send
#define recv ts_recv
#define select ts_select
#define close ts_close
#define bind ts_bind
#define listen ts_listen
#define write ts_write
#define read ts_read
#define getaddrinfo ts_getaddrinfo
#define freeaddrinfo ts_freeaddrinfo
#define fd_set ts_fd_set
#define timeval ts_timeval
#define FD_ZERO TS_FD_ZERO
#define FD_SET TS_FD_SET
#define FD_CLR TS_FD_CLR
#define FD_ISSET TS_FD_ISSET
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Module macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/*===========================================================================*/
/* Module inline functions. */
/*===========================================================================*/
#endif /* TSSOCKETS_H */

View File

@ -23,6 +23,7 @@
#include "ch.h"
#include "chobjfifos.h"
#include "chtssi.h"
#include "tsproxystubs.h"
#include "tssockstub.h"
#include <string.h>
#include <ctype.h>
@ -31,13 +32,6 @@
/* Module local definitions. */
/*===========================================================================*/
#define METHOD_MAX_PARAMS 6
#define STUB_MAX_OPS 32
#define OP_PRMDIR_NONE 0
#define OP_PRMDIR_IN 1
#define OP_PRMDIR_OUT 2
/*===========================================================================*/
/* Module exported variables. */
/*===========================================================================*/
@ -45,231 +39,35 @@
/*===========================================================================*/
/* Module local types. */
/*===========================================================================*/
typedef struct stub_op stub_op_t;
typedef enum {FREE=0, CALLING, PENDING} op_state_t;
typedef struct stub_param {
uint32_t dir;
uint32_t val;
uint32_t size;
} stub_parm_t;
typedef struct stub_op {
uint32_t op_code; /* e.g. connect, recv, sendv, close, etc.*/
op_state_t op_state; /* calling, pending, free.*/
stub_parm_t op_p[METHOD_MAX_PARAMS];
thread_reference_t op_wthdp; /* TS internal client thread (the caller).*/
} stub_op_t;
/*===========================================================================*/
/* Module local variables. */
/*===========================================================================*/
static objects_fifo_t ops_fifo;
static msg_t ops_msgs[STUB_MAX_OPS];
static struct stub_op ops[STUB_MAX_OPS] = {0};
static bool tsSkelIsReady = false;
static stub_ctx_t stub_ctx;
/*===========================================================================*/
/* Module local functions. */
/*===========================================================================*/
static bool isOpValid(stub_op_t *op)
{
if ((op < &ops[0]) || (op >= &ops[STUB_MAX_OPS]))
return FALSE;
if (((char *)op - (char *)&ops[0]) % sizeof ops[0])
return FALSE;
return TRUE;
}
/**
* @brief Implement an a call to a NSEC function.
* @details It activates the channel between the stubs service and
* the skels daemon running in the nsec world.
* To do it, it uses an event to signal the skels
* daemon that a new op request is ready to be executed.
* Behind the scenes, the skels daemon will then gets the op, calling
* the stubs service via smc. The daemon executes it and then calls
* the stubs service again to post the result and to wake up the
* calling thread of this function.
*
* @param[in] op the 'remote' method description.
*
* @return the return value of 'remote' method.
*/
static uint32_t callRemote(stub_op_t *op) {
uint32_t r;
chSysLock();
chFifoSendObjectI(&ops_fifo, op);
chEvtBroadcastFlagsI(&tsEventSource, EVT_F_SOCK_NEW_OP);
chThdSuspendS(&op->op_wthdp);
chSysUnlock();
r = op->op_code;
chFifoReturnObject(&ops_fifo, op);
return r;
}
static stub_op_t *getNewOp(void) {
stub_op_t *op = chFifoTakeObjectTimeout(&ops_fifo, TIME_INFINITE);
memset(op, 0, sizeof *op);
op->op_state = CALLING;
return op;
}
/*===========================================================================*/
/* Module exported functions. */
/*===========================================================================*/
/**
* @brief The stubs service.
* @details And this is where the magic happens.
* @brief The sockets stub service.
*/
THD_WORKING_AREA(waTsStubsService, 1024);
THD_FUNCTION(TsStubsService, tsstate) {
ts_state_t *svcp = tsstate;
skel_req_t *skrp;
stub_op_t *op;
msg_t r;
int i;
chFifoObjectInit(&ops_fifo, sizeof (stub_op_t), STUB_MAX_OPS,
sizeof (uint8_t), ops, ops_msgs);
for (;/* ever */;) {
/* Wait a service request.*/
(void)tssiWaitRequest(svcp);
skrp = (skel_req_t *)TS_GET_DATA(svcp);
r = SMC_SVC_OK;
/* Process the request.*/
if (TS_GET_DATALEN(svcp) != sizeof (skel_req_t)) {
TS_SET_STATUS(svcp, SMC_SVC_INVALID);
continue;
}
switch (skrp->req) {
case SKEL_REQ_READY:
tsSkelIsReady = true;
break;
case SKEL_REQ_GETOP:
/* The nsec skeleton calls us to get a new op ready to be executed.*/
if (chFifoReceiveObjectTimeout(&ops_fifo, (void **)&op, TIME_IMMEDIATE) ==
MSG_TIMEOUT) {
/* no op ready to be executed.*/
r = SMC_SVC_NHND;
break;
}
skrp->stub_op = (uint32_t)op;
skrp->stub_op_code = op->op_code;
/* Pass all the 'by value' arguments from stub to skel.*/
for (i = 0; i < METHOD_MAX_PARAMS; ++i) {
if (op->op_p[i].dir == OP_PRMDIR_NONE)
skrp->stub_op_p[i] = op->op_p[i].val;
}
op->op_state = PENDING;
break;
case SKEL_REQ_CPYPRMS:
/* The nsec skel calls us to get a copy of the 'in' parameters of
the specified op.
An 'in' parameter is an indirect argument, that is an argument
the value of which is a pointer to a memory buffer, that
must be copied in a non secure memory buffer.
It represents data to be consumed by the callee.*/
op = (stub_op_t *)skrp->stub_op;
if (!isOpValid(op) || op->op_state != PENDING ||
op->op_code != skrp->stub_op_code) {
r = SMC_SVC_INVALID;
break;
}
/* Copy all 'in' parameters.
For each parameter check that the destination memory area
is in the non secure memory arena.*/
for (i = 0; i < METHOD_MAX_PARAMS; ++i) {
if ((op->op_p[i].dir & OP_PRMDIR_IN) == 0)
continue;
if (!tsIsAddrSpaceValid((void *)skrp->stub_op_p[i], op->op_p[i].size)) {
r = SMC_SVC_INVALID;
break;
}
memcpy((void *)skrp->stub_op_p[i], (void *)op->op_p[i].val,
op->op_p[i].size);
}
break;
case SKEL_REQ_PUTRES:
/* The nsec skel calls us to put a copy of the 'out' parameters of
the specified op.
An 'out' parameter is an indirect argument, that is an argument
the value of which is a pointer to a memory buffer, that
must be copied in a secure memory buffer.
It represents data produced by the callee.*/
op = (stub_op_t *)skrp->stub_op;
if (!isOpValid(op) || op->op_state != PENDING ||
op->op_code != skrp->stub_op_code) {
r = SMC_SVC_INVALID;
break;
}
/* Copy all 'out' parameters.
For each parameter check that the source memory area
is in the non secure memory arena, and that the size returned
fits in the caller buffer size.*/
for (i = 0; i < METHOD_MAX_PARAMS; ++i) {
if ((op->op_p[i].dir & OP_PRMDIR_OUT) == 0)
continue;
if (!tsIsAddrSpaceValid((void *)skrp->stub_op_p[i], skrp->stub_op_p_sz[i])
|| (skrp->stub_op_p_sz[i] > op->op_p[i].size)) {
r = SMC_SVC_INVALID;
break;
}
memcpy((void *)op->op_p[i].val, (void *)skrp->stub_op_p[i],
skrp->stub_op_p_sz[i]);
}
if (r != SMC_SVC_OK)
break;
/* Set the return value of the 'remote' callee method,
and wake up the caller.*/
op->op_code = skrp->stub_op_result;
chThdResume(&op->op_wthdp, MSG_OK);
break;
default:
r = SMC_SVC_INVALID;
break;
}
/* Set the response.*/
TS_SET_STATUS(svcp, r);
}
}
/**
* @brief Is the skeletons daemon ready to operate?
* @details It is used at the startup to synchronize the
* stub service with the skeleton daemon.
*/
void tsWaitStubSkelReady(void) {
while (!tsSkelIsReady) {
chThdSleepMilliseconds(100);
}
THD_WORKING_AREA(waTsSocksStubsService, 1024);
THD_FUNCTION(TsSocksStubsService, tsstatep) {
stub_ctx.event_flag = EVT_F_SOCK_NEW_OP;
TsStubService((ts_state_t *)tsstatep, &stub_ctx);
}
/**
* @brief The sockets API.
*/
int socket(int domain, int type, int protocol) {
stub_op_t *op = getNewOp();
op->op_code = STUB_OP_SOCKET;
stub_op_t *op = getNewOp(&stub_ctx);
op->op_code = SOCK_OP_SOCKET;
op->op_p[0].dir = OP_PRMDIR_NONE;
op->op_p[0].val = (uint32_t)domain;
op->op_p[1].dir = OP_PRMDIR_NONE;
@ -280,8 +78,8 @@ int socket(int domain, int type, int protocol) {
}
int connect(int s, const struct sockaddr *name, socklen_t namelen) {
stub_op_t *op = getNewOp();
op->op_code = STUB_OP_CONNECT;
stub_op_t *op = getNewOp(&stub_ctx);
op->op_code = SOCK_OP_CONNECT;
op->op_p[0].dir = OP_PRMDIR_NONE;
op->op_p[0].val = (uint32_t)s;
op->op_p[1].dir = OP_PRMDIR_IN;
@ -293,16 +91,16 @@ int connect(int s, const struct sockaddr *name, socklen_t namelen) {
}
int close(int s) {
stub_op_t *op = getNewOp();
op->op_code = STUB_OP_CLOSE;
stub_op_t *op = getNewOp(&stub_ctx);
op->op_code = SOCK_OP_CLOSE;
op->op_p[0].dir = OP_PRMDIR_NONE;
op->op_p[0].val = (uint32_t)s;
return (int)callRemote(op);
}
int recv(int s, void *mem, size_t len, int flags) {
stub_op_t *op = getNewOp();
op->op_code = STUB_OP_RECV;
stub_op_t *op = getNewOp(&stub_ctx);
op->op_code = SOCK_OP_RECV;
op->op_p[0].dir = OP_PRMDIR_NONE;
op->op_p[0].val = (uint32_t)s;
op->op_p[1].dir = OP_PRMDIR_OUT;
@ -316,8 +114,8 @@ int recv(int s, void *mem, size_t len, int flags) {
}
int send(int s, const void *dataptr, size_t size, int flags) {
stub_op_t *op = getNewOp();
op->op_code = STUB_OP_SEND;
stub_op_t *op = getNewOp(&stub_ctx);
op->op_code = SOCK_OP_SEND;
op->op_p[0].dir = OP_PRMDIR_NONE;
op->op_p[0].val = (uint32_t)s;
op->op_p[1].dir = OP_PRMDIR_IN;
@ -332,8 +130,8 @@ int send(int s, const void *dataptr, size_t size, int flags) {
int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
struct timeval *timeout) {
stub_op_t *op = getNewOp();
op->op_code = STUB_OP_SELECT;
stub_op_t *op = getNewOp(&stub_ctx);
op->op_code = SOCK_OP_SELECT;
op->op_p[0].dir = OP_PRMDIR_NONE;
op->op_p[0].val = (uint32_t)maxfdp1;
op->op_p[1].dir = OP_PRMDIR_IN|OP_PRMDIR_OUT;
@ -352,8 +150,8 @@ int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
}
int bind(int s, const struct sockaddr *name, socklen_t namelen) {
stub_op_t *op = getNewOp();
op->op_code = STUB_OP_BIND;
stub_op_t *op = getNewOp(&stub_ctx);
op->op_code = SOCK_OP_BIND;
op->op_p[0].dir = OP_PRMDIR_NONE;
op->op_p[0].val = (uint32_t)s;
op->op_p[1].dir = OP_PRMDIR_IN;
@ -365,8 +163,8 @@ int bind(int s, const struct sockaddr *name, socklen_t namelen) {
}
int listen(int s, int backlog) {
stub_op_t *op = getNewOp();
op->op_code = STUB_OP_LISTEN;
stub_op_t *op = getNewOp(&stub_ctx);
op->op_code = SOCK_OP_LISTEN;
op->op_p[0].dir = OP_PRMDIR_NONE;
op->op_p[0].val = (uint32_t)s;
op->op_p[1].dir = OP_PRMDIR_NONE;

View File

@ -28,7 +28,7 @@
#include "ch.h"
#include "ccportab.h"
#include "tscommon.h"
/*===========================================================================*/
/* Module constants. */
/*===========================================================================*/
@ -376,9 +376,8 @@ extern "C" {
int listen(int s, int backlog);
in_addr_t inet_addr(const char *cp);
int inet_aton(const char *cp, struct in_addr *addr);
void tsWaitStubSkelReady(void);
THD_FUNCTION(TsStubsService, tsstate);
extern THD_WORKING_AREA(waTsStubsService, 1024);
THD_FUNCTION(TsSocksStubsService, tsstatep);
extern THD_WORKING_AREA(waTsSocksStubsService, 1024);
#ifdef __cplusplus
}
#endif