arc: add z_arch_user_string_nlen

Safely measure the length of a potentially dubious string.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2018-06-22 15:15:12 -07:00 committed by Andrew Boie
commit b1dec2992e
2 changed files with 79 additions and 6 deletions

View file

@ -18,6 +18,15 @@
#include <kernel.h>
#include <kernel_structs.h>
#include <misc/printk.h>
#include <exc_handle.h>
#ifdef CONFIG_USERSPACE
Z_EXC_DECLARE(z_arch_user_string_nlen);
static const struct z_exc_handle exceptions[] = {
Z_EXC_HANDLE(z_arch_user_string_nlen)
};
#endif
/*
* @brief Fault handler
@ -26,15 +35,25 @@
* and is responsible only for reporting the error. Once reported, it then
* invokes the user provided routine _SysFatalErrorHandler() which is
* responsible for implementing the error handling policy.
*
* @return This function does not return.
*/
void _Fault(const NANO_ESF *esf)
void _Fault(NANO_ESF *esf)
{
u32_t vector, code, parameter;
u32_t exc_addr = _arc_v2_aux_reg_read(_ARC_V2_EFA);
u32_t ecr = _arc_v2_aux_reg_read(_ARC_V2_ECR);
#ifdef CONFIG_USERSPACE
for (int i = 0; i < ARRAY_SIZE(exceptions); i++) {
u32_t start = (u32_t)exceptions[i].start;
u32_t end = (u32_t)exceptions[i].end;
if (esf->pc >= start && esf->pc < end) {
esf->pc = (u32_t)(exceptions[i].fixup);
return;
}
}
#endif
vector = _ARC_V2_ECR_VECTOR(ecr);
code = _ARC_V2_ECR_CODE(ecr);
parameter = _ARC_V2_ECR_PARAMETER(ecr);

View file

@ -47,9 +47,10 @@
GTEXT(_arc_userspace_enter)
GTEXT(_arc_do_syscall)
GTEXT(_user_thread_entry_wrapper)
GTEXT(z_arch_user_string_nlen)
GTEXT(z_arch_user_string_nlen_fault_start)
GTEXT(z_arch_user_string_nlen_fault_end)
GTEXT(z_arch_user_string_nlen_fixup)
/*
* @brief Wrapper for _thread_entry in the case of user thread
*
@ -211,3 +212,56 @@ SECTION_FUNC(TEXT, _arc_do_syscall)
mov r6, 0
rtie
/*
* size_t z_arch_user_string_nlen(const char *s, size_t maxsize, int *err_arg)
*/
SECTION_FUNC(TEXT, z_arch_user_string_nlen)
/* int err; */
sub_s sp,sp,0x4
/* Initial error value (-1 failure), store at [sp,0] */
mov_s r3, -1
st_s r3, [sp, 0]
/* Loop setup.
* r12 (position locator) = s - 1
* r0 (length counter return value)) = 0
* lp_count = maxsize + 1
* */
sub r12, r0, 0x1
mov_s r0, 0
add_s r1, r1, 1
mov lp_count, r1
strlen_loop:
z_arch_user_string_nlen_fault_start:
/* is the byte at ++r12 a NULL? if so, we're done. Might fault! */
ldb.aw r1, [r12, 1]
z_arch_user_string_nlen_fault_end:
brne_s r1, 0, not_null
strlen_done:
/* Success, set err to 0 */
mov_s r1, 0
st_s r1, [sp, 0]
z_arch_user_string_nlen_fixup:
/* *err_arg = err; Pop stack and return */
ld_s r1, [sp, 0]
add_s sp, sp, 4
j_s.d [blink]
st_s r1, [r2, 0]
not_null:
/* check if we've hit the maximum, if so we're done. */
brne.d.nt lp_count, 0x1, inc_len
sub lp_count, lp_count, 0x1
b_s strlen_done
inc_len:
/* increment length measurement, loop again */
add_s r0, r0, 1
b_s strlen_loop