Added sbExec() function.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@15358 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2022-01-15 13:29:11 +00:00
parent c65d695093
commit c1ee7b08b5
6 changed files with 240 additions and 128 deletions

View File

@ -55,7 +55,7 @@ endif
# Stack size to be allocated to the Cortex-M process stack. This stack is # Stack size to be allocated to the Cortex-M process stack. This stack is
# the stack used by the main() thread. # the stack used by the main() thread.
ifeq ($(USE_PROCESS_STACKSIZE),) ifeq ($(USE_PROCESS_STACKSIZE),)
USE_PROCESS_STACKSIZE = 0x400 USE_PROCESS_STACKSIZE = 0x800
endif endif
# Stack size to the allocated to the Cortex-M main/exceptions stack. This # Stack size to the allocated to the Cortex-M main/exceptions stack. This

View File

@ -107,7 +107,7 @@ static const char *sbx1_envp[] = {
NULL NULL
}; };
static THD_WORKING_AREA(waUnprivileged1, 1024); static THD_WORKING_AREA(waUnprivileged1, 2048);
/*===========================================================================*/ /*===========================================================================*/
/* Main and generic code. */ /* Main and generic code. */
@ -245,9 +245,9 @@ int main(void) {
if (CH_RET_IS_ERROR(ret)) { if (CH_RET_IS_ERROR(ret)) {
chSysHalt("VFS"); chSysHalt("VFS");
} }
sbPosixRegisterDescriptor(&sbx1, STDIN_FILENO, (vfs_node_c *)roAddRef(np)); sbRegisterDescriptor(&sbx1, STDIN_FILENO, (vfs_node_c *)roAddRef(np));
sbPosixRegisterDescriptor(&sbx1, STDOUT_FILENO, (vfs_node_c *)roAddRef(np)); sbRegisterDescriptor(&sbx1, STDOUT_FILENO, (vfs_node_c *)roAddRef(np));
sbPosixRegisterDescriptor(&sbx1, STDERR_FILENO, (vfs_node_c *)roAddRef(np)); sbRegisterDescriptor(&sbx1, STDERR_FILENO, (vfs_node_c *)roAddRef(np));
vfsClose(np); vfsClose(np);
#if 0 #if 0
@ -259,9 +259,9 @@ int main(void) {
if (CH_RET_IS_ERROR(ret)) { if (CH_RET_IS_ERROR(ret)) {
chSysHalt("VFS"); chSysHalt("VFS");
} }
sbPosixRegisterDescriptor(&sbx2, STDIN_FILENO, (vfs_node_c *)roAddRef(np)); sbRegisterDescriptor(&sbx2, STDIN_FILENO, (vfs_node_c *)roAddRef(np));
sbPosixRegisterDescriptor(&sbx2, STDOUT_FILENO, (vfs_node_c *)roAddRef(np)); sbRegisterDescriptor(&sbx2, STDOUT_FILENO, (vfs_node_c *)roAddRef(np));
sbPosixRegisterDescriptor(&sbx2, STDERR_FILENO, (vfs_node_c *)roAddRef(np)); sbRegisterDescriptor(&sbx2, STDERR_FILENO, (vfs_node_c *)roAddRef(np));
vfsClose(np); vfsClose(np);
#endif #endif
@ -299,29 +299,15 @@ int main(void) {
if (palReadLine(LINE_BUTTON)) { if (palReadLine(LINE_BUTTON)) {
if (!sbIsThreadRunningX(&sbx1)) { if (!sbIsThreadRunningX(&sbx1)) {
/* Loading sandbox code.*/ /* Running the sandbox.*/
ret = sbElfLoadFile((vfs_driver_c *)&sb1_root_overlay_driver, ret = sbExec(&sbx1, "/bin/msh.elf",
"/bin/msh.elf", waUnprivileged1, sizeof (waUnprivileged1), NORMALPRIO - 1,
&sbx1.config->regions[0].area); sbx1_argv, sbx1_envp);
if (CH_RET_IS_ERROR(ret)) { if (CH_RET_IS_ERROR(ret)) {
chSysHalt("ELF"); chprintf((BaseSequentialStream *)&SD2, "SBX1 launch failed (%08lx)\r\n", ret);
} chThdSleepMilliseconds(1000);
/* Starting sandboxed thread 1.*/
if (sbStartThread(&sbx1, "sbx1",
waUnprivileged1, sizeof (waUnprivileged1), NORMALPRIO - 1,
sbx1_argv, sbx1_envp) == NULL) {
chSysHalt("sbx1 failed");
} }
} }
#if 0
static uint8_t loadbuf[1024];
static memory_area_t ma = {loadbuf, sizeof (loadbuf)};
ret = sbElfLoadFile((vfs_driver_c *)&sb1_root_overlay_driver, "/bin/app.elf", &ma);
if (CH_RET_IS_ERROR(ret)) {
chSysHalt("ELF");
}
#endif
} }
} }
} }

View File

@ -105,34 +105,34 @@ void sb_strv_copy(const char *sp[], void *dp, int n) {
*(vp + n) = NULL; *(vp + n) = NULL;
} }
bool sb_is_valid_read_range(sb_class_t *sbcp, const void *start, size_t size) { bool sb_is_valid_read_range(sb_class_t *sbp, const void *start, size_t size) {
const sb_memory_region_t *rp = &sbcp->config->regions[0]; const sb_memory_region_t *rp = &sbp->config->regions[0];
do { do {
if (rp->used && chMemIsSpaceWithinX(&rp->area, start, size)) { if (rp->used && chMemIsSpaceWithinX(&rp->area, start, size)) {
return true; return true;
} }
rp++; rp++;
} while (rp < &sbcp->config->regions[SB_CFG_NUM_REGIONS]); } while (rp < &sbp->config->regions[SB_CFG_NUM_REGIONS]);
return false; return false;
} }
bool sb_is_valid_write_range(sb_class_t *sbcp, void *start, size_t size) { bool sb_is_valid_write_range(sb_class_t *sbp, void *start, size_t size) {
const sb_memory_region_t *rp = &sbcp->config->regions[0]; const sb_memory_region_t *rp = &sbp->config->regions[0];
do { do {
if (rp->used && chMemIsSpaceWithinX(&rp->area, start, size)) { if (rp->used && chMemIsSpaceWithinX(&rp->area, start, size)) {
return rp->writeable; return rp->writeable;
} }
rp++; rp++;
} while (rp < &sbcp->config->regions[SB_CFG_NUM_REGIONS]); } while (rp < &sbp->config->regions[SB_CFG_NUM_REGIONS]);
return false; return false;
} }
size_t sb_check_string(sb_class_t *sbcp, const char *s, size_t max) { size_t sb_check_string(sb_class_t *sbp, const char *s, size_t max) {
const sb_memory_region_t *rp = &sbcp->config->regions[0]; const sb_memory_region_t *rp = &sbp->config->regions[0];
do { do {
if (rp->used) { if (rp->used) {
@ -142,13 +142,13 @@ size_t sb_check_string(sb_class_t *sbcp, const char *s, size_t max) {
} }
} }
rp++; rp++;
} while (rp < &sbcp->config->regions[SB_CFG_NUM_REGIONS]); } while (rp < &sbp->config->regions[SB_CFG_NUM_REGIONS]);
return (size_t)0; return (size_t)0;
} }
size_t sb_check_pointers_array(sb_class_t *sbcp, const void *pp[], size_t max) { size_t sb_check_pointers_array(sb_class_t *sbp, const void *pp[], size_t max) {
const sb_memory_region_t *rp = &sbcp->config->regions[0]; const sb_memory_region_t *rp = &sbp->config->regions[0];
do { do {
if (rp->used) { if (rp->used) {
@ -158,21 +158,21 @@ size_t sb_check_pointers_array(sb_class_t *sbcp, const void *pp[], size_t max) {
} }
} }
rp++; rp++;
} while (rp < &sbcp->config->regions[SB_CFG_NUM_REGIONS]); } while (rp < &sbp->config->regions[SB_CFG_NUM_REGIONS]);
return (size_t)0; return (size_t)0;
} }
size_t sb_check_strings_array(sb_class_t *sbcp, const char *pp[], size_t max) { size_t sb_check_strings_array(sb_class_t *sbp, const char *pp[], size_t max) {
const char *s; const char *s;
size_t n; size_t n;
n = sb_check_pointers_array(sbcp, (const void **)pp, max); n = sb_check_pointers_array(sbp, (const void **)pp, max);
if (n > (size_t)0) { if (n > (size_t)0) {
while ((s = *pp++) != NULL) { while ((s = *pp++) != NULL) {
size_t sn; size_t sn;
sn = sb_check_string(sbcp, s, max - n); sn = sb_check_string(sbp, s, max - n);
if (sn == (size_t)0) { if (sn == (size_t)0) {
return (size_t)0; return (size_t)0;
} }
@ -187,27 +187,27 @@ size_t sb_check_strings_array(sb_class_t *sbcp, const char *pp[], size_t max) {
/** /**
* @brief Sandbox object initialization. * @brief Sandbox object initialization.
* *
* @param[out] sbcp pointer to the sandbox object * @param[out] sbp pointer to the sandbox object
* @param[in] config pointer to the sandbox configuration * @param[in] config pointer to the sandbox configuration
* *
* @init * @init
*/ */
void sbObjectInit(sb_class_t *sbcp, const sb_config_t *config) { void sbObjectInit(sb_class_t *sbp, const sb_config_t *config) {
sbcp->config = config; sbp->config = config;
sbcp->tp = NULL; sbp->tp = NULL;
#if CH_CFG_USE_MESSAGES == TRUE #if CH_CFG_USE_MESSAGES == TRUE
sbcp->msg_tp = NULL; sbp->msg_tp = NULL;
#endif #endif
#if CH_CFG_USE_EVENTS == TRUE #if CH_CFG_USE_EVENTS == TRUE
chEvtObjectInit(&sbcp->es); chEvtObjectInit(&sbp->es);
#endif #endif
} }
/** /**
* @brief Starts a sandboxed thread. * @brief Starts a sandboxed thread.
* *
* @param[in] sbcp pointer to a @p sb_class_t structure * @param[in] sbp pointer to a @p sb_class_t structure
* @param[in] name name to be assigned to the thread * @param[in] name name to be assigned to the thread
* @param[out] wsp pointer to a working area dedicated to the thread stack * @param[out] wsp pointer to a working area dedicated to the thread stack
* @param[in] size size of the working area * @param[in] size size of the working area
@ -217,12 +217,12 @@ void sbObjectInit(sb_class_t *sbcp, const sb_config_t *config) {
* @return The thread pointer. * @return The thread pointer.
* @retval NULL if the sandbox thread creation failed. * @retval NULL if the sandbox thread creation failed.
*/ */
thread_t *sbStartThread(sb_class_t *sbcp, const char *name, thread_t *sbStartThread(sb_class_t *sbp, const char *name,
void *wsp, size_t size, tprio_t prio, void *wsp, size_t size, tprio_t prio,
const char *argv[], const char *envp[]) { const char *argv[], const char *envp[]) {
thread_t *utp; thread_t *utp;
const sb_header_t *sbhp; const sb_header_t *sbhp;
const sb_config_t *config = sbcp->config; const sb_config_t *config = sbp->config;
void *usp, *uargv, *uenvp; void *usp, *uargv, *uenvp;
size_t envsize, argsize, parsize; size_t envsize, argsize, parsize;
int uargc, uenvc; int uargc, uenvc;
@ -290,7 +290,7 @@ thread_t *sbStartThread(sb_class_t *sbcp, const char *name,
.prio = prio, .prio = prio,
.u_pc = sbhp->hdr_entry, .u_pc = sbhp->hdr_entry,
.u_psp = (uint32_t)usp, .u_psp = (uint32_t)usp,
.arg = (void *)sbcp .arg = (void *)sbp
}; };
#if PORT_SWITCHED_REGIONS_NUMBER > 0 #if PORT_SWITCHED_REGIONS_NUMBER > 0
for (unsigned i = 0U; i < PORT_SWITCHED_REGIONS_NUMBER; i++) { for (unsigned i = 0U; i < PORT_SWITCHED_REGIONS_NUMBER; i++) {
@ -301,7 +301,7 @@ thread_t *sbStartThread(sb_class_t *sbcp, const char *name,
utp = chThdCreateUnprivileged(&utd); utp = chThdCreateUnprivileged(&utd);
/* For messages exchange.*/ /* For messages exchange.*/
sbcp->tp = utp; sbp->tp = utp;
return utp; return utp;
} }
@ -309,20 +309,149 @@ thread_t *sbStartThread(sb_class_t *sbcp, const char *name,
/** /**
* @brief Verifies if the sandbox thread is running. * @brief Verifies if the sandbox thread is running.
* *
* @param[in] sbcp pointer to a @p sb_class_t structure * @param[in] sbp pointer to a @p sb_class_t structure
* @return The thread status. * @return The thread status.
* *
* @api * @api
*/ */
bool sbIsThreadRunningX(sb_class_t *sbcp) { bool sbIsThreadRunningX(sb_class_t *sbp) {
if (sbcp->tp == NULL) { if (sbp->tp == NULL) {
return false; return false;
} }
return !chThdTerminatedX(sbcp->tp); return !chThdTerminatedX(sbp->tp);
} }
#if (SB_CFG_ENABLE_VFS == TRUE) || defined(__DOXYGEN__)
/**
* @brief Execute an elf file within a sandbox.
* @note The file is loaded into region zero of the sandbox which is
* assumed to be used for both code and data, extra regions are
* not touched by this function.
*
* @param[in] sbp pointer to a @p sb_class_t structure
* @param[in] pathname file to be executed
* @param[in] argv arguments to be passed to the sandbox
* @param[in] envp environment variables to be passed to the sandbox
* @return The operation result.
*
* @api
*/
msg_t sbExec(sb_class_t *sbp, const char *pathname,
void *wsp, size_t size, tprio_t prio,
const char *argv[], const char *envp[]) {
const sb_config_t *config = sbp->config;
memory_area_t ma = config->regions[0].area;
const sb_header_t *sbhp;
msg_t ret;
void *usp, *uargv, *uenvp;
size_t envsize, argsize, parsize;
int uargc, uenvc;
/* Setting up an initial stack for the sandbox.*/
usp = (void *)(config->regions[0].area.base + config->regions[0].area.size);
/* Allocating space for environment variables.*/
envsize = sb_strv_getsize(envp, &uenvc);
PUSHSPACE(usp, envsize);
uenvp = usp;
/* Allocating space for arguments.*/
argsize = sb_strv_getsize(argv, &uargc);
PUSHSPACE(usp, argsize);
uargv = usp;
/* Allocating space for parameters.*/
if (MEM_IS_ALIGNED(usp, PORT_STACK_ALIGN)) {
parsize = sizeof (int) + sizeof (const char **) + sizeof (const char **) + sizeof (int);
}
else {
parsize = sizeof (const char **) + sizeof (const char **) + sizeof (int);
}
PUSHSPACE(usp, parsize);
/* Checking stack allocation.*/
if (!chMemIsSpaceWithinX(&config->regions[0].area,
usp, envsize + argsize + parsize)) {
return CH_RET_ENOMEM;
}
/* Adjusting the size of the memory area object, we don't want the loaded
elf file to overwrite the initialized stack.*/
ma.size -= envsize + argsize + parsize;
/* Initializing stack.*/
sb_strv_copy(envp, uenvp, uenvc);
sb_strv_copy(argv, uargv, uargc);
*((uint32_t *)usp + 2) = (uint32_t)uenvp;
*((uint32_t *)usp + 1) = (uint32_t)uargv;
*((uint32_t *)usp + 0) = (uint32_t)uargc;
/* Loading sandbox code into the specified memory area.*/
ret = sbElfLoadFile(config->vfs_driver, pathname, &ma);
CH_RETURN_ON_ERROR(ret);
/* Header location.*/
sbhp = (const sb_header_t *)(void *)ma.base;
/* Checking header magic numbers.*/
if ((sbhp->hdr_magic1 != SB_MAGIC1) || (sbhp->hdr_magic2 != SB_MAGIC2)) {
return CH_RET_ENOEXEC;
}
/* Checking header size.*/
if (sbhp->hdr_size != sizeof (sb_header_t)) {
return CH_RET_ENOEXEC;
}
/* Checking header entry point.*/
if (!chMemIsSpaceWithinX(&ma, (const void *)sbhp->hdr_entry, (size_t)2)) {
return CH_RET_EFAULT;
}
/* Everything OK, starting the unprivileged thread inside the sandbox.*/
unprivileged_thread_descriptor_t utd = {
.name = pathname,
.wbase = (stkalign_t *)wsp,
.wend = (stkalign_t *)wsp + (size / sizeof (stkalign_t)),
.prio = prio,
.u_pc = sbhp->hdr_entry,
.u_psp = (uint32_t)usp,
.arg = (void *)sbp
};
#if PORT_SWITCHED_REGIONS_NUMBER > 0
for (unsigned i = 0U; i < PORT_SWITCHED_REGIONS_NUMBER; i++) {
utd.regions[i] = config->mpuregs[i];
}
#endif
sbp->tp = chThdCreateUnprivileged(&utd);
if (sbp->tp == NULL) {
return CH_RET_ENOMEM;
}
return CH_RET_SUCCESS;
}
/**
* @brief Registers a file descriptor on a sandbox.
*
* @param[in] sbp pointer to a @p sb_class_t structure
* @param[in] fd file descriptor to be assigned
* @param[in] np VFS node to be registered on the file descriptor
*
* @api
*/
void sbRegisterDescriptor(sb_class_t *sbp, int fd, vfs_node_c *np) {
chDbgAssert(sb_is_available_descriptor(&sbp->io, fd), "invalid file descriptor");
sbp->io.vfs_nodes[fd] = np;
}
#endif
#if (CH_CFG_USE_WAITEXIT == TRUE) || defined(__DOXYGEN__) #if (CH_CFG_USE_WAITEXIT == TRUE) || defined(__DOXYGEN__)
/** /**
* @brief Blocks the execution of the invoking thread until the specified * @brief Blocks the execution of the invoking thread until the specified
@ -330,21 +459,21 @@ bool sbIsThreadRunningX(sb_class_t *sbcp) {
* @pre The configuration option @p CH_CFG_USE_WAITEXIT must be enabled in * @pre The configuration option @p CH_CFG_USE_WAITEXIT must be enabled in
* order to use this function. * order to use this function.
* *
* @param[in] sbcp pointer to a @p sb_class_t structure * @param[in] sbp pointer to a @p sb_class_t structure
* @return The exit code from the terminated sandbox thread. * @return The exit code from the terminated sandbox thread.
* @retval MSG_RESET Sandbox thread not started. * @retval MSG_RESET Sandbox thread not started.
* *
* @api * @api
*/ */
msg_t sbWaitThread(sb_class_t *sbcp) { msg_t sbWaitThread(sb_class_t *sbp) {
msg_t msg; msg_t msg;
if (sbcp->tp == NULL) { if (sbp->tp == NULL) {
return MSG_RESET; return MSG_RESET;
} }
msg = chThdWait(sbcp->tp); msg = chThdWait(sbp->tp);
sbcp->tp = NULL; sbp->tp = NULL;
return msg; return msg;
} }
@ -354,7 +483,7 @@ msg_t sbWaitThread(sb_class_t *sbcp) {
/** /**
* @brief Sends a message to a sandboxed thread. * @brief Sends a message to a sandboxed thread.
* *
* @param[in] sbcp pointer to the sandbox object * @param[in] sbp pointer to the sandbox object
* @param[in] msg message to be sent * @param[in] msg message to be sent
* @param[in] timeout the number of ticks before the operation timeouts, * @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed: * the following special values are allowed:
@ -367,28 +496,28 @@ msg_t sbWaitThread(sb_class_t *sbcp) {
* *
* @api * @api
*/ */
msg_t sbSendMessageTimeout(sb_class_t *sbcp, msg_t sbSendMessageTimeout(sb_class_t *sbp,
msg_t msg, msg_t msg,
sysinterval_t timeout) { sysinterval_t timeout) {
thread_t *ctp = __sch_get_currthread(); thread_t *ctp = __sch_get_currthread();
chDbgCheck(sbcp != NULL); chDbgCheck(sbp != NULL);
chSysLock(); chSysLock();
/* Sending the message.*/ /* Sending the message.*/
ctp->u.sentmsg = msg; ctp->u.sentmsg = msg;
__ch_msg_insert(&sbcp->tp->msgqueue, ctp); __ch_msg_insert(&sbp->tp->msgqueue, ctp);
if (sbcp->tp->state == CH_STATE_WTMSG) { if (sbp->tp->state == CH_STATE_WTMSG) {
(void) chSchReadyI(sbcp->tp); (void) chSchReadyI(sbp->tp);
} }
msg = chSchGoSleepTimeoutS(CH_STATE_SNDMSGQ, timeout); msg = chSchGoSleepTimeoutS(CH_STATE_SNDMSGQ, timeout);
/* If a timeout occurred while the boxed thread already received the message /* If a timeout occurred while the boxed thread already received the message
then this thread needs to "unregister" as sender, the boxed error will then this thread needs to "unregister" as sender, the boxed error will
get SB_ERR_EBUSY when/if trying to reply.*/ get SB_ERR_EBUSY when/if trying to reply.*/
if ((msg == MSG_TIMEOUT) && (sbcp->msg_tp == ctp)) { if ((msg == MSG_TIMEOUT) && (sbp->msg_tp == ctp)) {
sbcp->msg_tp = NULL; sbp->msg_tp = NULL;
} }
chSysUnlock(); chSysUnlock();

View File

@ -93,21 +93,28 @@ extern "C" {
#endif #endif
void port_syscall(struct port_extctx *ctxp, uint32_t n); void port_syscall(struct port_extctx *ctxp, uint32_t n);
size_t sb_strv_getsize(const char *v[], int *np); size_t sb_strv_getsize(const char *v[], int *np);
bool sb_is_valid_read_range(sb_class_t *sbcp, const void *start, size_t size); void sb_strv_copy(const char *sp[], void *dp, int n);
bool sb_is_valid_write_range(sb_class_t *sbcp, void *start, size_t size); bool sb_is_valid_read_range(sb_class_t *sbp, const void *start, size_t size);
size_t sb_check_string(sb_class_t *sbcp, const char *s, size_t max); bool sb_is_valid_write_range(sb_class_t *sbp, void *start, size_t size);
size_t sb_check_pointers_array(sb_class_t *sbcp, const void *pp[], size_t max); size_t sb_check_string(sb_class_t *sbp, const char *s, size_t max);
size_t sb_check_strings_array(sb_class_t *sbcp, const char *pp[], size_t max); size_t sb_check_pointers_array(sb_class_t *sbp, const void *pp[], size_t max);
void sbObjectInit(sb_class_t *sbcp, const sb_config_t *config); size_t sb_check_strings_array(sb_class_t *sbp, const char *pp[], size_t max);
thread_t *sbStartThread(sb_class_t *sbcp, const char *name, void sbObjectInit(sb_class_t *sbp, const sb_config_t *config);
thread_t *sbStartThread(sb_class_t *sbp, const char *name,
void *wsp, size_t size, tprio_t prio, void *wsp, size_t size, tprio_t prio,
const char *argv[], const char *envp[]); const char *argv[], const char *envp[]);
bool sbIsThreadRunningX(sb_class_t *sbcp); bool sbIsThreadRunningX(sb_class_t *sbp);
#if SB_CFG_ENABLE_VFS == TRUE
msg_t sbExec(sb_class_t *sbp, const char *pathname,
void *wsp, size_t size, tprio_t prio,
const char *argv[], const char *envp[]);
void sbRegisterDescriptor(sb_class_t *sbp, int fd, vfs_node_c *np);
#endif
#if CH_CFG_USE_WAITEXIT == TRUE #if CH_CFG_USE_WAITEXIT == TRUE
msg_t sbWaitThread(sb_class_t *sbcp); msg_t sbWaitThread(sb_class_t *sbp);
#endif #endif
#if CH_CFG_USE_MESSAGES == TRUE #if CH_CFG_USE_MESSAGES == TRUE
msg_t sbSendMessageTimeout(sb_class_t *sbcp, msg_t sbSendMessageTimeout(sb_class_t *sbp,
msg_t msg, msg_t msg,
sysinterval_t timeout); sysinterval_t timeout);
#endif #endif
@ -135,7 +142,7 @@ static inline void sbHostInit(void) {
/** /**
* @brief Sends a message to a sandboxed thread. * @brief Sends a message to a sandboxed thread.
* *
* @param[in] sbcp pointer to the sandbox object * @param[in] sbp pointer to the sandbox object
* @param[in] msg message to be sent * @param[in] msg message to be sent
* @return The returned message. * @return The returned message.
* @retval MSG_RESET if the exchange aborted, sandboxed thread API usage * @retval MSG_RESET if the exchange aborted, sandboxed thread API usage
@ -143,9 +150,9 @@ static inline void sbHostInit(void) {
* *
* @api * @api
*/ */
static inline msg_t sbSendMessage(sb_class_t *sbcp, msg_t msg) { static inline msg_t sbSendMessage(sb_class_t *sbp, msg_t msg) {
return sbSendMessageTimeout(sbcp, msg, TIME_INFINITE); return sbSendMessageTimeout(sbp, msg, TIME_INFINITE);
} }
#endif /* CH_CFG_USE_MESSAGES == TRUE */ #endif /* CH_CFG_USE_MESSAGES == TRUE */
@ -153,40 +160,40 @@ static inline msg_t sbSendMessage(sb_class_t *sbcp, msg_t msg) {
/** /**
* @brief Adds a set of event flags directly to the specified sandbox. * @brief Adds a set of event flags directly to the specified sandbox.
* *
* @param[in] sbcp pointer to the sandbox object * @param[in] sbp pointer to the sandbox object
* @param[in] events the events set to be ORed * @param[in] events the events set to be ORed
* *
* @iclass * @iclass
*/ */
static inline void sbEvtSignalI(sb_class_t *sbcp, eventmask_t events) { static inline void sbEvtSignalI(sb_class_t *sbp, eventmask_t events) {
chEvtSignalI(sbcp->tp, events); chEvtSignalI(sbp->tp, events);
} }
/** /**
* @brief Adds a set of event flags directly to the specified sandbox. * @brief Adds a set of event flags directly to the specified sandbox.
* *
* @param[in] sbcp pointer to the sandbox object * @param[in] sbp pointer to the sandbox object
* @param[in] events the events set to be ORed * @param[in] events the events set to be ORed
* *
* @api * @api
*/ */
static inline void sbEvtSignal(sb_class_t *sbcp, eventmask_t events) { static inline void sbEvtSignal(sb_class_t *sbp, eventmask_t events) {
chEvtSignal(sbcp->tp, events); chEvtSignal(sbp->tp, events);
} }
/** /**
* @brief Returns the sandbox event source object. * @brief Returns the sandbox event source object.
* *
* @param[in] sbcp pointer to the sandbox object * @param[in] sbp pointer to the sandbox object
* @return The pointer to the event source object. * @return The pointer to the event source object.
* *
* @xclass * @xclass
*/ */
static inline event_source_t *sbGetEventSourceX(sb_class_t *sbcp) { static inline event_source_t *sbGetEventSourceX(sb_class_t *sbp) {
return &sbcp->es; return &sbp->es;
} }
#endif /* CH_CFG_USE_EVENTS == TRUE */ #endif /* CH_CFG_USE_EVENTS == TRUE */

View File

@ -65,22 +65,7 @@ static msg_t create_descriptor(sb_ioblock_t *iop,
return CH_RET_EMFILE; return CH_RET_EMFILE;
} }
#endif /* SB_CFG_ENABLE_VFS == TRUE */
static bool is_valid_descriptor(int fd) {
return (fd >= 0) && (fd < SB_CFG_FD_NUM);
}
static bool is_available_descriptor(sb_ioblock_t *iop, int fd) {
return (fd >= 0) && (fd < SB_CFG_FD_NUM) && (iop->vfs_nodes[fd] == NULL);
}
static bool is_existing_descriptor(sb_ioblock_t *iop, int fd) {
return (fd >= 0) && (fd < SB_CFG_FD_NUM) && (iop->vfs_nodes[fd] != NULL);
}
#endif
/*===========================================================================*/ /*===========================================================================*/
/* Module exported functions. */ /* Module exported functions. */
@ -116,7 +101,7 @@ int sb_posix_open(const char *path, int flags) {
int sb_posix_close(int fd) { int sb_posix_close(int fd) {
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
if (!is_existing_descriptor(&sbp->io, fd)) { if (!sb_is_existing_descriptor(&sbp->io, fd)) {
return CH_RET_EBADF; return CH_RET_EBADF;
} }
@ -131,7 +116,7 @@ int sb_posix_dup(int fd) {
vfs_node_c *np; vfs_node_c *np;
msg_t ret; msg_t ret;
if (!is_existing_descriptor(&sbp->io, fd)) { if (!sb_is_existing_descriptor(&sbp->io, fd)) {
return CH_RET_EBADF; return CH_RET_EBADF;
} }
@ -152,11 +137,11 @@ int sb_posix_dup(int fd) {
int sb_posix_dup2(int oldfd, int newfd) { int sb_posix_dup2(int oldfd, int newfd) {
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
if (!is_existing_descriptor(&sbp->io, oldfd)) { if (!sb_is_existing_descriptor(&sbp->io, oldfd)) {
return CH_RET_EBADF; return CH_RET_EBADF;
} }
if (!is_valid_descriptor(oldfd)) { if (!sb_is_valid_descriptor(oldfd)) {
return CH_RET_EBADF; return CH_RET_EBADF;
} }
@ -182,7 +167,7 @@ int sb_posix_fstat(int fd, struct stat *statbuf) {
return CH_RET_EFAULT; return CH_RET_EFAULT;
} }
if (!is_existing_descriptor(&sbp->io, fd)) { if (!sb_is_existing_descriptor(&sbp->io, fd)) {
return CH_RET_EBADF; return CH_RET_EBADF;
} }
@ -204,7 +189,7 @@ ssize_t sb_posix_read(int fd, void *buf, size_t count) {
return CH_RET_EFAULT; return CH_RET_EFAULT;
} }
if (!is_existing_descriptor(&sbp->io, fd)) { if (!sb_is_existing_descriptor(&sbp->io, fd)) {
return CH_RET_EBADF; return CH_RET_EBADF;
} }
@ -222,7 +207,7 @@ ssize_t sb_posix_write(int fd, const void *buf, size_t count) {
return CH_RET_EFAULT; return CH_RET_EFAULT;
} }
if (!is_existing_descriptor(&sbp->io, fd)) { if (!sb_is_existing_descriptor(&sbp->io, fd)) {
return CH_RET_EBADF; return CH_RET_EBADF;
} }
@ -240,7 +225,7 @@ off_t sb_posix_lseek(int fd, off_t offset, int whence) {
return CH_RET_EINVAL; return CH_RET_EINVAL;
} }
if (!is_existing_descriptor(&sbp->io, fd)) { if (!sb_is_existing_descriptor(&sbp->io, fd)) {
return CH_RET_EBADF; return CH_RET_EBADF;
} }
@ -266,7 +251,7 @@ ssize_t sb_posix_getdents(int fd, void *buf, size_t count) {
return (ssize_t)CH_RET_EFAULT; return (ssize_t)CH_RET_EFAULT;
} }
if (!is_existing_descriptor(&sbp->io, fd)) { if (!sb_is_existing_descriptor(&sbp->io, fd)) {
return (ssize_t)CH_RET_EBADF; return (ssize_t)CH_RET_EBADF;
} }
@ -307,13 +292,6 @@ ssize_t sb_posix_getdents(int fd, void *buf, size_t count) {
return (ssize_t)ret; return (ssize_t)ret;
} }
void sbPosixRegisterDescriptor(sb_class_t *sbp, int fd, vfs_node_c *np) {
chDbgAssert(is_available_descriptor(&sbp->io, fd), "invalid file descriptor");
sbp->io.vfs_nodes[fd] = np;
}
#else /* Fallbacks for when there is no VFS.*/ #else /* Fallbacks for when there is no VFS.*/
uint32_t sb_posix_open(const char *pathname, uint32_t flags) { uint32_t sb_posix_open(const char *pathname, uint32_t flags) {

View File

@ -68,9 +68,6 @@ extern "C" {
ssize_t sb_posix_write(int fd, const void *buf, size_t count); ssize_t sb_posix_write(int fd, const void *buf, size_t count);
off_t sb_posix_lseek(int fd, off_t offset, int whence); off_t sb_posix_lseek(int fd, off_t offset, int whence);
ssize_t sb_posix_getdents(int fd, void *buf, size_t count); ssize_t sb_posix_getdents(int fd, void *buf, size_t count);
#if SB_CFG_ENABLE_VFS == TRUE
void sbPosixRegisterDescriptor(sb_class_t *sbp, int fd, vfs_node_c *np);
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
@ -79,6 +76,21 @@ extern "C" {
/* Module inline functions. */ /* Module inline functions. */
/*===========================================================================*/ /*===========================================================================*/
static inline bool sb_is_valid_descriptor(int fd) {
return (fd >= 0) && (fd < SB_CFG_FD_NUM);
}
static inline bool sb_is_available_descriptor(sb_ioblock_t *iop, int fd) {
return (fd >= 0) && (fd < SB_CFG_FD_NUM) && (iop->vfs_nodes[fd] == NULL);
}
static inline bool sb_is_existing_descriptor(sb_ioblock_t *iop, int fd) {
return (fd >= 0) && (fd < SB_CFG_FD_NUM) && (iop->vfs_nodes[fd] != NULL);
}
#endif /* SBPOSIX_H */ #endif /* SBPOSIX_H */
/** @} */ /** @} */