git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@15274 27425a3e-05d8-49a3-a47f-9c15f0e5edd8

This commit is contained in:
Giovanni Di Sirio 2021-12-28 14:01:59 +00:00
parent 4b9b255235
commit c6015620db
10 changed files with 234 additions and 126 deletions

View File

@ -52,6 +52,7 @@
#define CH_RET_EBADF CH_ENCODE_ERROR(EBADF) /* Bad file number */ #define CH_RET_EBADF CH_ENCODE_ERROR(EBADF) /* Bad file number */
#define CH_RET_ENOMEM CH_ENCODE_ERROR(ENOMEM) /* Not enough space */ #define CH_RET_ENOMEM CH_ENCODE_ERROR(ENOMEM) /* Not enough space */
#define CH_RET_EACCES CH_ENCODE_ERROR(EACCES) /* Permission denied */ #define CH_RET_EACCES CH_ENCODE_ERROR(EACCES) /* Permission denied */
#define CH_RET_EFAULT CH_ENCODE_ERROR(EACCES) /* Bad address */
#define CH_RET_EEXIST CH_ENCODE_ERROR(EEXIST) /* File exists */ #define CH_RET_EEXIST CH_ENCODE_ERROR(EEXIST) /* File exists */
#define CH_RET_ENOTDIR CH_ENCODE_ERROR(ENOTDIR) /* Not a directory */ #define CH_RET_ENOTDIR CH_ENCODE_ERROR(ENOTDIR) /* Not a directory */
#define CH_RET_EISDIR CH_ENCODE_ERROR(EISDIR) /* Is a directory */ #define CH_RET_EISDIR CH_ENCODE_ERROR(EISDIR) /* Is a directory */

View File

@ -73,6 +73,9 @@ typedef struct {
extern "C" { extern "C" {
#endif #endif
#if CH_CFG_USE_MEMCHECKS == TRUE #if CH_CFG_USE_MEMCHECKS == TRUE
bool chMemIsStringWithinX(const memory_area_t *map,
const char *s,
size_t n);
bool chMemIsAreaContainedX(const memory_area_t areas[], bool chMemIsAreaContainedX(const memory_area_t areas[],
const void *base, const void *base,
size_t size); size_t size);
@ -93,10 +96,9 @@ extern "C" {
/** /**
* @brief Memory area check. * @brief Memory area check.
* @details Checks if specified area belongs to the specified area. * @details Checks if specified area belongs to the specified memory area.
* *
* @param[in] map pointer to an array of valid areas terminated with * @param[in] map pointer to a @p memory_area_t structure
* a zero element
* @param[in] p pointer to the area to be checked * @param[in] p pointer to the area to be checked
* @param[in] size size of the area to be checked * @param[in] size size of the area to be checked
* @return The test result. * @return The test result.

View File

@ -76,6 +76,39 @@ CC_WEAK memory_area_t __ch_mem_readable_areas[] = {
/* Module exported functions. */ /* Module exported functions. */
/*===========================================================================*/ /*===========================================================================*/
/**
* @brief String check.
* @details Checks if specified string is entirely contained in the specified
* memory area.
*
* @param[in] map pointer to a @p memory_area_t structure
* @param[in] s pointer to the string to be checked
* @param[in] n maximum expected size of the string
* @return The test result.
* @retval false if the string is entirely contained within one of the
* specified areas.
* @retval true if the string check failed.
*
* @xclass
*/
bool chMemIsStringWithinX(const memory_area_t *map, const char *s, size_t n) {
const char *base = (const char *)map->base;
const char *end = (const char *)base + map->size;
if (s >= base) {
while ((s < end) && (n > 0U)) {
if (*s == '\0') {
return true;
}
s++;
n--;
}
}
return false;
}
/** /**
* @brief Memory area check. * @brief Memory area check.
* @details Checks if specified area belongs to one of the specified areas. * @details Checks if specified area belongs to one of the specified areas.

View File

@ -1,97 +0,0 @@
/*
ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014,
2015,2016,2017,2018,2019,2020,2021 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 version 3 of the License.
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 sb/common/sberr.h
* @brief ARMv7-M sandbox common macros and structures.
*
* @addtogroup ARM_SANDBOX_ERRORS
* @{
*/
#ifndef SBERR_H
#define SBERR_H
/*===========================================================================*/
/* Module constants. */
/*===========================================================================*/
/**
* @name Sandbox API error codes
* @{
*/
#define SB_ERR_NOERROR 0U
#define SB_ERR_ENOENT ((uint32_t)(-2))
#define SB_ERR_EFAULT ((uint32_t)(-14))
#define SB_ERR_EBUSY ((uint32_t)(-16))
#define SB_ERR_EINVAL ((uint32_t)(-22))
#define SB_ERR_ESPIPE ((uint32_t)(-29))
#define SB_ERR_EBADFD ((uint32_t)(-81))
#define SB_ERR_ENOSYS ((uint32_t)(-88))
#define SB_ERR_ERRORMASK 0xFFFFFF00U
#define SB_ERR_ISERROR(x) (((uint32_t)(x) & SB_ERR_ERRORMASK) == SB_ERR_ERRORMASK)
/** @} */
/**
* @name Posix-like function codes
* @{
*/
#define SB_POSIX_OPEN 1
#define SB_POSIX_CLOSE 2
#define SB_POSIX_READ 3
#define SB_POSIX_WRITE 4
#define SB_POSIX_LSEEK 5
/** @} */
/*===========================================================================*/
/* Module pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Module macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
/*===========================================================================*/
/* Module inline functions. */
/*===========================================================================*/
#endif /* SBERR_H */
/** @} */

View File

@ -94,6 +94,10 @@
#error "SB_CFG_ENABLE_VFS not defined in sbconf.h" #error "SB_CFG_ENABLE_VFS not defined in sbconf.h"
#endif #endif
#if !defined(SB_CFG_FD_NUM) || defined(__DOXYGEN__)
#error "SB_CFG_FD_NUM not defined in sbconf.h"
#endif
/* License checks.*/ /* License checks.*/
#if !defined(CH_CUSTOMER_LIC_SB) || !defined(CH_LICENSE_FEATURES) #if !defined(CH_CUSTOMER_LIC_SB) || !defined(CH_LICENSE_FEATURES)
#error "malformed chlicense.h" #error "malformed chlicense.h"
@ -162,10 +166,13 @@ extern "C" {
/* Module inline functions. */ /* Module inline functions. */
/*===========================================================================*/ /*===========================================================================*/
#include "sberr.h" #include "hal.h"
#include "errcodes.h"
#include "sbsysc.h"
#include "sbposix.h" #include "sbposix.h"
#include "sbhost.h"
#include "sbapi.h" #include "sbapi.h"
#include "sbhost.h"
#endif /* SBHOST_H */ #endif /* SBHOST_H */

View File

@ -915,7 +915,7 @@ const port_syscall_t sb_syscalls[256] = {
static void sb_undef_handler(struct port_extctx *ectxp) { static void sb_undef_handler(struct port_extctx *ectxp) {
ectxp->r0 = SB_ERR_ENOSYS; ectxp->r0 = CH_RET_ENOSYS;
} }
static thread_t *sb_msg_wait_timeout_s(sysinterval_t timeout) { static thread_t *sb_msg_wait_timeout_s(sysinterval_t timeout) {
@ -979,7 +979,7 @@ void sb_api_stdio(struct port_extctx *ectxp) {
ectxp->r3); ectxp->r3);
break; break;
default: default:
ectxp->r0 = SB_ERR_ENOSYS; ectxp->r0 = CH_RET_ENOSYS;
break; break;
} }
} }
@ -994,7 +994,7 @@ void sb_api_exit(struct port_extctx *ectxp) {
chSysUnlock(); chSysUnlock();
/* Cannot get here.*/ /* Cannot get here.*/
ectxp->r0 = SB_ERR_ENOSYS; ectxp->r0 = CH_RET_ENOSYS;
} }
void sb_api_get_systime(struct port_extctx *ectxp) { void sb_api_get_systime(struct port_extctx *ectxp) {
@ -1014,14 +1014,14 @@ void sb_api_sleep(struct port_extctx *ectxp) {
chThdSleep(interval); chThdSleep(interval);
} }
ectxp->r0 = SB_ERR_NOERROR; ectxp->r0 = CH_RET_SUCCESS;
} }
void sb_api_sleep_until_windowed(struct port_extctx *ectxp) { void sb_api_sleep_until_windowed(struct port_extctx *ectxp) {
chThdSleepUntilWindowed((systime_t )ectxp->r0, (systime_t )ectxp->r1); chThdSleepUntilWindowed((systime_t )ectxp->r0, (systime_t )ectxp->r1);
ectxp->r0 = SB_ERR_NOERROR; ectxp->r0 = CH_RET_SUCCESS;
} }
void sb_api_wait_message(struct port_extctx *ectxp) { void sb_api_wait_message(struct port_extctx *ectxp) {
@ -1038,12 +1038,12 @@ void sb_api_wait_message(struct port_extctx *ectxp) {
thread_t *tp = sbcp->msg_tp; thread_t *tp = sbcp->msg_tp;
sbcp->msg_tp = NULL; sbcp->msg_tp = NULL;
chMsgReleaseS(tp, MSG_RESET); chMsgReleaseS(tp, MSG_RESET);
ectxp->r0 = SB_ERR_EBUSY; ectxp->r0 = MSG_RESET;
} }
chSysUnlock(); chSysUnlock();
#else #else
ectxp->r0 = SB_ERR_NOT_IMPLEMENTED; ectxp->r0 = CH_RET_ENOSYS;
#endif #endif
} }
@ -1057,15 +1057,15 @@ void sb_api_reply_message(struct port_extctx *ectxp) {
thread_t *tp = sbcp->msg_tp; thread_t *tp = sbcp->msg_tp;
sbcp->msg_tp = NULL; sbcp->msg_tp = NULL;
chMsgReleaseS(tp, (msg_t )ectxp->r0); chMsgReleaseS(tp, (msg_t )ectxp->r0);
ectxp->r0 = SB_ERR_NOERROR; ectxp->r0 = CH_RET_SUCCESS;
} }
else { else {
ectxp->r0 = SB_ERR_EBUSY; ectxp->r0 = MSG_RESET;
} }
chSysUnlock(); chSysUnlock();
#else #else
ectxp->r0 = SB_ERR_NOT_IMPLEMENTED; ectxp->r0 = CH_RET_ENOSYS;
#endif #endif
} }
@ -1075,7 +1075,7 @@ void sb_api_wait_one_timeout(struct port_extctx *ectxp) {
ectxp->r0 = (uint32_t)chEvtWaitOneTimeout((eventmask_t )ectxp->r0, ectxp->r0 = (uint32_t)chEvtWaitOneTimeout((eventmask_t )ectxp->r0,
(sysinterval_t )ectxp->r1); (sysinterval_t )ectxp->r1);
#else #else
ectxp->r0 = SB_ERR_NOT_IMPLEMENTED; ectxp->r0 = CH_RET_ENOSYS;
#endif #endif
} }
@ -1085,7 +1085,7 @@ void sb_api_wait_any_timeout(struct port_extctx *ectxp) {
ectxp->r0 = (uint32_t)chEvtWaitAnyTimeout((eventmask_t )ectxp->r0, ectxp->r0 = (uint32_t)chEvtWaitAnyTimeout((eventmask_t )ectxp->r0,
(sysinterval_t )ectxp->r1); (sysinterval_t )ectxp->r1);
#else #else
ectxp->r0 = SB_ERR_NOT_IMPLEMENTED; ectxp->r0 = CH_RET_ENOSYS;
#endif #endif
} }
@ -1095,7 +1095,7 @@ void sb_api_wait_all_timeout(struct port_extctx *ectxp) {
ectxp->r0 = (uint32_t)chEvtWaitAllTimeout((eventmask_t )ectxp->r0, ectxp->r0 = (uint32_t)chEvtWaitAllTimeout((eventmask_t )ectxp->r0,
(sysinterval_t )ectxp->r1); (sysinterval_t )ectxp->r1);
#else #else
ectxp->r0 = SB_ERR_NOT_IMPLEMENTED; ectxp->r0 = CH_RET_ENOSYS;
#endif #endif
} }
@ -1104,9 +1104,9 @@ void sb_api_broadcast_flags(struct port_extctx *ectxp) {
sb_class_t *sbcp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; sb_class_t *sbcp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
chEvtBroadcastFlags(&sbcp->es, (eventflags_t )ectxp->r0); chEvtBroadcastFlags(&sbcp->es, (eventflags_t )ectxp->r0);
ectxp->r0 = SB_ERR_NOERROR; ectxp->r0 = CH_RET_SUCCESS;
#else #else
ectxp->r0 = SB_ERR_NOT_IMPLEMENTED; ectxp->r0 = CH_RET_ENOSYS;
#endif #endif
} }

View File

@ -74,7 +74,7 @@ bool sb_is_valid_write_range(sb_class_t *sbcp, void *start, size_t size) {
const sb_memory_region_t *rp = &sbcp->config->regions[0]; const sb_memory_region_t *rp = &sbcp->config->regions[0];
do { do {
if (chMemIsAreaContainedX(&rp->area, start, size)) { if (chMemIsAreaWithinX(&rp->area, start, size)) {
return rp->writeable; return rp->writeable;
} }
rp++; rp++;
@ -83,6 +83,19 @@ bool sb_is_valid_write_range(sb_class_t *sbcp, void *start, size_t size) {
return false; return false;
} }
bool sb_is_valid_string_range(sb_class_t *sbcp, const char *s, size_t n) {
const sb_memory_region_t *rp = &sbcp->config->regions[0];
do {
if (chMemIsAreaWithinX(&rp->area, s, n)) {
return true;
}
rp++;
} while (rp < &sbcp->config->regions[SB_CFG_NUM_REGIONS]);
return false;
}
/** /**
* @brief Sandbox object initialization. * @brief Sandbox object initialization.
* *

View File

@ -28,9 +28,6 @@
#ifndef SBHOST_H #ifndef SBHOST_H
#define SBHOST_H #define SBHOST_H
#include "sberr.h"
#include "sbapi.h"
/*===========================================================================*/ /*===========================================================================*/
/* Module constants. */ /* Module constants. */
/*===========================================================================*/ /*===========================================================================*/
@ -151,8 +148,17 @@ typedef struct {
thread_t *msg_tp; thread_t *msg_tp;
#endif #endif
#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__) #if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
/**
* @brief Sandbox events source.
*/
event_source_t es; event_source_t es;
#endif #endif
#if (SB_CFG_ENABLE_VFS == TRUE) || defined(__DOXYGEN__)
/**
* @brief VFS bindings for Posix API.
*/
sb_ioblock_t io;
#endif
} sb_class_t; } sb_class_t;
/** /**
@ -193,6 +199,7 @@ extern "C" {
void port_syscall(struct port_extctx *ctxp, uint32_t n); void port_syscall(struct port_extctx *ctxp, uint32_t n);
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 *sbcp, const void *start, size_t size);
bool sb_is_valid_write_range(sb_class_t *sbcp, void *start, size_t size); bool sb_is_valid_write_range(sb_class_t *sbcp, void *start, size_t size);
bool sb_is_valid_string_range(sb_class_t *sbcp, const char *s, size_t n);
void sbObjectInit(sb_class_t *sbcp); void sbObjectInit(sb_class_t *sbcp);
void sbStart(sb_class_t *sbcp, const sb_config_t *config); void sbStart(sb_class_t *sbcp, const sb_config_t *config);
thread_t *sbStartThread(sb_class_t *sbcp, const sb_config_t *config, thread_t *sbStartThread(sb_class_t *sbcp, const sb_config_t *config,

View File

@ -48,10 +48,127 @@
/* Module local functions. */ /* Module local functions. */
/*===========================================================================*/ /*===========================================================================*/
static msg_t create_descriptor(sb_ioblock_t *iop,
vfs_node_c *np,
uint8_t attributes) {
unsigned fd;
for (fd = 0U; fd < SB_CFG_FD_NUM; fd++) {
if (iop->vfs_nodes[fd] == NULL) {
iop->vfs_nodes[fd] = np;
iop->attributes[fd] = attributes;
return (msg_t)fd;
}
}
return CH_RET_EMFILE;
}
static bool is_valid_descriptor(sb_ioblock_t *iop, int fd) {
return (fd >= 0) && (fd < SB_CFG_FD_NUM) && (iop->vfs_nodes[fd] != NULL);
}
/*===========================================================================*/ /*===========================================================================*/
/* Module exported functions. */ /* Module exported functions. */
/*===========================================================================*/ /*===========================================================================*/
#if (SB_CFG_ENABLE_VFS == TRUE) || defined(__DOXYGEN__)
int sb_posix_open(const char *path, int flags) {
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
vfs_file_node_c *fnp = NULL;
msg_t ret;
if (!sb_is_valid_string_range(sbp, (void *)path, VFS_CFG_PATHLEN_MAX)) {
return CH_RET_EFAULT;
}
do {
ret = vfsDrvOpenFile(sbp->io.vfs_driver, path, (unsigned)flags, &fnp);
CH_BREAK_ON_ERROR(ret);
ret = create_descriptor(&sbp->io, (vfs_node_c *)fnp, 0);
CH_BREAK_ON_ERROR(ret);
return (int)ret;
} while (true);
if (fnp != NULL) {
vfsCloseFile(fnp);
}
return (int)ret;
}
int sb_posix_close(int fd) {
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
if (!is_valid_descriptor(&sbp->io, fd)) {
return CH_RET_EBADF;
}
if (sbp->io.attributes[fd] == 0) {
vfsCloseFile((vfs_file_node_c *)sbp->io.vfs_nodes[fd]);
}
else {
vfsCloseDirectory((vfs_directory_node_c *)sbp->io.vfs_nodes[fd]);
}
sbp->io.vfs_nodes[fd] = NULL;
return CH_RET_SUCCESS;
}
ssize_t sb_posix_read(int fd, void *buf, size_t count) {
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
if (!sb_is_valid_read_range(sbp, (void *)buf, count)) {
return CH_RET_EFAULT;
}
if (!is_valid_descriptor(&sbp->io, fd)) {
return CH_RET_EBADF;
}
if (sbp->io.attributes[fd] != 0) {
return CH_RET_EISDIR;
}
return vfsReadFile((vfs_file_node_c *)sbp->io.vfs_nodes[fd], buf, count);
}
ssize_t sb_posix_write(int fd, const void *buf, size_t count) {
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
if (!sb_is_valid_write_range(sbp, (void *)buf, count)) {
return CH_RET_EFAULT;
}
if (!is_valid_descriptor(&sbp->io, fd)) {
return CH_RET_EBADF;
}
if (sbp->io.attributes[fd] != 0) {
return CH_RET_EISDIR;
}
return vfsWriteFile((vfs_file_node_c *)sbp->io.vfs_nodes[fd], buf, count);
}
off_t sb_posix_lseek(int fd, off_t offset, int whence) {
(void)offset;
(void)whence;
if ((fd == 0U) || (fd == 1U) || (fd == 2U)) {
return CH_RET_ESPIPE;
}
return CH_RET_EBADF;
}
#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) {
(void)pathname; (void)pathname;
@ -132,5 +249,6 @@ uint32_t sb_posix_lseek(uint32_t fd, uint32_t offset, uint32_t whence) {
return SB_ERR_EBADFD; return SB_ERR_EBADFD;
} }
#endif
/** @} */ /** @} */

View File

@ -28,6 +28,10 @@
#ifndef SBPOSIX_H #ifndef SBPOSIX_H
#define SBPOSIX_H #define SBPOSIX_H
#if (SB_CFG_ENABLE_VFS == TRUE) || defined(__DOXYGEN__)
#include "vfs.h"
#endif
/*===========================================================================*/ /*===========================================================================*/
/* Module constants. */ /* Module constants. */
/*===========================================================================*/ /*===========================================================================*/
@ -44,6 +48,26 @@
/* Module data structures and types. */ /* Module data structures and types. */
/*===========================================================================*/ /*===========================================================================*/
#if (SB_CFG_ENABLE_VFS == TRUE) || defined(__DOXYGEN__)
/**
* @brief Type of a sandbox I/O structure.
*/
typedef struct {
/**
* @brief VFS driver associated to the sandbox as root.
*/
vfs_driver_c *vfs_driver;
/**
* @brief VFS nodes associated to file descriptors.
*/
vfs_node_c *vfs_nodes[SB_CFG_FD_NUM];
/**
* @brief Extra attributes added to the VFS nodes.
*/
uint8_t attributes[SB_CFG_FD_NUM];
} sb_ioblock_t;
#endif
/*===========================================================================*/ /*===========================================================================*/
/* Module macros. */ /* Module macros. */
/*===========================================================================*/ /*===========================================================================*/
@ -55,11 +79,11 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
uint32_t sb_posix_open(const char *pathname, uint32_t flags); int sb_posix_open(const char *path, int flags);
uint32_t sb_posix_close(uint32_t fd); int sb_posix_close(int fd);
uint32_t sb_posix_read(uint32_t fd, uint8_t *buf, size_t count); ssize_t sb_posix_read(int fd, void *buf, size_t count);
uint32_t sb_posix_write(uint32_t fd, const uint8_t *buf, size_t count); ssize_t sb_posix_write(int fd, const void *buf, size_t count);
uint32_t sb_posix_lseek(uint32_t fd, uint32_t offset, uint32_t whence); off_t sb_posix_lseek(int fd, off_t offset, int whence);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif