Browse Source

make system calls safer/clean up headers

wrap some libc functions that do system calls (terminal output)
wrap read/write with syscall guard
define real_read/write (next dynamic linker find for read/write)
guard system calls in remaining code
introduce native_internhal.h
throw out some debug statements that break things
clean up includes a bit
declare board_init in native_internhal.h
add -ldl to LINKFLAGS for cpu/syscalls
dev/timer
Ludwig Ortmann 9 years ago
parent
commit
7b9d199ec8
  1. 2
      boards/native/Makefile.include
  2. 37
      boards/native/drivers/native-uart0.c
  3. 2
      boards/native/include/board_internal.h
  4. 6
      cpu/native/hwtimer_cpu.c
  5. 26
      cpu/native/include/cpu.h
  6. 57
      cpu/native/include/native_internal.h
  7. 2
      cpu/native/include/nativenet_internal.h
  8. 68
      cpu/native/irq_cpu.c
  9. 11
      cpu/native/lpm_cpu.c
  10. 8
      cpu/native/native_cpu.c
  11. 5
      cpu/native/net/tap.c
  12. 10
      cpu/native/rtc/posix-rtc.c
  13. 20
      cpu/native/startup.c
  14. 154
      cpu/native/syscalls.c

2
boards/native/Makefile.include

@ -14,7 +14,7 @@ export OBJCOPY = $(PREFIX)objcopy
FLASHER = lpc2k_pgm
TERM = pyterm.py
LINKFLAGS += -m32 -gc
LINKFLAGS += -m32 -gc -ldl
ifeq ($(strip $(PORT)),)
export PORT = /dev/ttyUSB0

37
boards/native/drivers/native-uart0.c

@ -6,6 +6,8 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <sys/select.h>
@ -13,21 +15,27 @@
#include "debug.h"
#include "board_uart0.h"
int _native_uart_in;
int _native_uart_out;
#include "native_internal.h"
static int _native_uart_in;
fd_set _native_uart_rfds;
inline int uart0_puts(char *astring, int length)
int uart0_puts(char *astring, int length)
{
int nwritten, offset;
nwritten = 0;
offset = 0;
_native_in_syscall = 1;
while ((length > 0) &&(nwritten = write(_native_uart_out, astring+offset, length-offset)) > 0) {
while (
(length - offset > 0) && (
(nwritten = write(
STDOUT_FILENO,
astring+offset,
length-offset)
) > 0)
) {
offset += nwritten;
}
if (nwritten == -1) {
@ -38,8 +46,6 @@ inline int uart0_puts(char *astring, int length)
errx(EXIT_FAILURE, "uart0_puts: Could not write to stdout. I don't know what to do now.");
}
_native_in_syscall = 0;
return length;
}
@ -53,8 +59,6 @@ void _native_handle_uart0_input()
return;
}
DEBUG("_native_handle_uart0_input\n");
_native_in_syscall = 0;
_native_in_isr = 1;
nread = read(_native_uart_in, buf, sizeof(buf));
if (nread == -1) {
@ -66,33 +70,28 @@ void _native_handle_uart0_input()
* with properly in #161 */
close(_native_uart_in);
_native_uart_in = -1;
warnx("stdin closed");
printf("stdin closed");
}
for(int pos = 0; pos < nread; pos++) {
uart0_handle_incoming(buf[pos]);
}
uart0_notify_thread();
_native_in_isr = 0;
thread_yield();
}
int _native_set_uart_fds(void)
{
DEBUG("_native_set_uart_fds");
FD_SET(_native_uart_in, &_native_rfds);
if (_native_uart_in != -1) {
FD_SET(_native_uart_in, &_native_rfds);
}
return _native_uart_in;
}
void _native_init_uart0()
{
_native_uart_out = STDOUT_FILENO;
_native_uart_in = STDIN_FILENO;
puts("RIOT native uart0 initialized.");
}
int putchar(int c) {
write(_native_uart_out, &c, 1);
return 0;
}

2
boards/native/include/board_internal.h

@ -4,3 +4,5 @@ void _native_handle_uart0_input(void);
void _native_init_uart0(void);
int _native_set_uart_fds(void);
#endif
void board_init(void);

6
cpu/native/hwtimer_cpu.c

@ -31,12 +31,14 @@
#include <signal.h>
#include <stdint.h>
#include <err.h>
#include "hwtimer.h"
#include "hwtimer_arch.h"
#include "hwtimer_cpu.h"
#include "cpu.h"
#include "cpu-conf.h"
#include "native_internal.h"
#define ENABLE_DEBUG (0)
@ -223,7 +225,7 @@ unsigned long hwtimer_arch_now(void)
DEBUG("hwtimer_arch_now()\n");
_native_in_syscall = 1;
_native_syscall_enter();
#ifdef __MACH__
clock_serv_t cclock;
mach_timespec_t mts;
@ -239,7 +241,7 @@ unsigned long hwtimer_arch_now(void)
}
#endif
_native_in_syscall = 0;
_native_syscall_leave();
native_hwtimer_now = ts2ticks(&t) - time_null;

26
cpu/native/include/cpu.h

@ -27,16 +27,22 @@
* http://sourceforge.net/p/predef/wiki/OperatingSystems/
*/
#ifdef BSD // BSD = (FreeBSD, Darwin, ...)
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE
#elif defined(__linux__)
#define __USE_GNU
#endif
#include <ucontext.h>
#ifdef BSD
#undef _XOPEN_SOURCE
#else
#include <ucontext.h>
#endif
#elif defined(__linux__)
#undef __USE_GNU
#ifndef _GNU_SOURCE
#define GNU_SOURCE
#include <ucontext.h>
#undef GNU_SOURCE
#else
#include <ucontext.h>
#endif
#endif // BSD/Linux
#include "kernel_internal.h"
#include "sched.h"
@ -62,15 +68,5 @@ int unregister_interrupt(int sig);
/* this should be defined elsewhere */
void thread_yield(void);
extern void _native_sig_leave_tramp(void);
extern ucontext_t *_native_cur_ctx, *_native_isr_ctx;
extern volatile unsigned int _native_saved_eip;
extern volatile int _native_in_isr;
extern volatile int _native_in_syscall;
extern volatile int _native_sigpend;
#ifdef MODULE_UART0
#include <sys/select.h>
extern fd_set _native_rfds;
#endif
/** @} */
#endif //_CPU_H

57
cpu/native/include/native_internal.h

@ -0,0 +1,57 @@
/**
* Native CPU internal declarations
*/
/**
* @ingroup arch
* @defgroup native_cpu Native CPU
* @{
* @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
*/
#ifndef _NATIVE_INTERNAL_H
#define _NATIVE_INTERNAL_H
//#include <signal.h>
/**
* internal functions
*/
void native_cpu_init(void);
void native_interrupt_init(void);
void native_irq_handler();
extern void _native_sig_leave_tramp(void);
void _native_syscall_leave();
void _native_syscall_enter();
/**
* external functions regularly wrapped in native for direct use
*/
extern ssize_t (*real_read)(int fd, void *buf, size_t count);
extern ssize_t (*real_write)(int fd, const void *buf, size_t count);
/**
* data structures
*/
extern volatile int native_interrupts_enabled;
extern volatile unsigned int _native_saved_eip;
extern int _sig_pipefd[2];
extern volatile int _native_sigpend;
extern volatile int _native_in_isr;
extern volatile int _native_in_syscall;
extern char __isr_stack[SIGSTKSZ];
extern char __end_stack[SIGSTKSZ];
extern ucontext_t native_isr_context;
extern ucontext_t end_context;
extern ucontext_t *_native_cur_ctx, *_native_isr_ctx;
#ifdef MODULE_UART0
#include <sys/select.h>
extern fd_set _native_rfds;
#endif
/** @} */
#endif /* _NATIVE_INTERNAL_H */

2
cpu/native/include/nativenet_internal.h

@ -37,7 +37,7 @@ struct rx_buffer_s {
char data[NATIVE_MAX_DATA_LENGTH];
};
extern struct rx_buffer_s _nativenet_rx_buffer[];
extern struct rx_buffer_s _nativenet_rx_buffer[RX_BUF_SIZE];
void _nativenet_handle_packet(radio_packet_t *packet);
#endif /* NATIVENET_INTERNAL_H */

68
cpu/native/irq_cpu.c

@ -13,6 +13,7 @@
* @file
* @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
*/
#include <err.h>
#include <string.h>
#include <unistd.h>
@ -39,24 +40,28 @@
#include "lpm.h"
#include "native_internal.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
volatile int native_interrupts_enabled;
extern volatile tcb_t *active_thread;
volatile int _native_sigpend;
volatile int native_interrupts_enabled;
volatile int _native_in_isr;
volatile int _native_in_syscall;
ucontext_t native_isr_context;
static sigset_t native_sig_set;
static char __isr_stack[SIGSTKSZ];
extern volatile tcb_t *active_thread;
volatile unsigned int _native_saved_eip;
char __isr_stack[SIGSTKSZ];
ucontext_t native_isr_context;
ucontext_t *_native_cur_ctx, *_native_isr_ctx;
int *process_heap_address;
static int pipefd[2];
volatile unsigned int _native_saved_eip;
volatile int _native_sigpend;
int _sig_pipefd[2];
struct int_handler_t {
void (*func)(void);
@ -64,10 +69,6 @@ struct int_handler_t {
static struct int_handler_t native_irq_handlers[255];
char sigalt_stk[SIGSTKSZ];
void native_irq_handler();
void print_thread_sigmask(ucontext_t *cp)
{
sigset_t *p = &cp->uc_sigmask;
@ -149,7 +150,7 @@ unsigned disableIRQ(void)
unsigned int prev_state;
sigset_t mask;
_native_in_syscall = 1;
_native_syscall_enter();
DEBUG("disableIRQ()\n");
if (_native_in_isr == 1) {
@ -179,7 +180,7 @@ unsigned disableIRQ(void)
native_interrupts_enabled = 0;
DEBUG("disableIRQ(): return\n");
_native_in_syscall = 0;
_native_syscall_leave();
return prev_state;
}
@ -191,7 +192,7 @@ unsigned enableIRQ(void)
{
unsigned int prev_state;
_native_in_syscall = 1;
_native_syscall_enter();
DEBUG("enableIRQ()\n");
if (_native_in_isr == 1) {
@ -204,21 +205,7 @@ unsigned enableIRQ(void)
prev_state = native_interrupts_enabled;
native_interrupts_enabled = 1;
//print_sigmasks();
//native_print_signals();
if ((_native_sigpend > 0) && (_native_in_isr == 0)) {
_native_cur_ctx = (ucontext_t *)active_thread->sp;
DEBUG("\n\n\t\treturn from syscall, calling native_irq_handler\n\n");
_native_in_syscall = 0;
DEBUG("enableIRQ: calling swapcontext()\n");
DEBUG("enableIRQ: _native_cur_ctx == %p, _native_isr_ctx == %p\n", _native_cur_ctx, _native_isr_ctx);
makecontext(&native_isr_context, native_irq_handler, 0);
swapcontext(_native_cur_ctx, _native_isr_ctx);
}
else {
_native_in_syscall = 0;
}
_native_syscall_leave();
DEBUG("enableIRQ(): return\n");
@ -264,16 +251,14 @@ int _native_popsig(void)
nleft = sizeof(int);
i = 0;
_native_in_syscall = 1;
while ((nleft > 0) && ((nread = read(pipefd[0], ((uint8_t*)&sig) + i, nleft)) != -1)) {
while ((nleft > 0) && ((nread = real_read(_sig_pipefd[0], ((uint8_t*)&sig) + i, nleft)) != -1)) {
i += nread;
nleft -= nread;
}
if (nread == -1) {
err(1, "_native_popsig(): read()");
err(1, "_native_popsig(): real_read()");
}
_native_in_syscall = 0;
return sig;
}
@ -318,13 +303,14 @@ void native_irq_handler()
void native_isr_entry(int sig, siginfo_t *info, void *context)
{
(void) info; /* unused at the moment */
DEBUG("\n\n\t\tnative_isr_entry\n\n");
//printf("\n\033[33m\n\t\tnative_isr_entry(%i)\n\n\033[0m", sig);
/* save the signal */
if (write(pipefd[1], &sig, sizeof(int)) == -1) {
err(1, "native_isr_entry(): write()");
if (real_write(_sig_pipefd[1], &sig, sizeof(int)) == -1) {
err(1, "native_isr_entry(): real_write()");
}
_native_sigpend++;
//real_write(STDOUT_FILENO, "sigpend\n", 8);
makecontext(&native_isr_context, native_irq_handler, 0);
_native_cur_ctx = (ucontext_t *)active_thread->sp;
@ -332,7 +318,7 @@ void native_isr_entry(int sig, siginfo_t *info, void *context)
/* XXX: Workaround safety check - whenever this happens it really
* indicates a bug in disableIRQ */
if (native_interrupts_enabled == 0) {
warnx("interrupts are off, but I caught a signal.");
//printf("interrupts are off, but I caught a signal.\n");
return;
}
@ -351,11 +337,12 @@ void native_isr_entry(int sig, siginfo_t *info, void *context)
((void*)(((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP]))
> ((void*)process_heap_address)
) {
DEBUG("\n\033[36mEIP:\t%p\nHEAP:\t%p\nnot switching\n\n\033[0m", (void*)((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP], (void*)process_heap_address);
//printf("\n\033[36mEIP:\t%p\nHEAP:\t%p\nnot switching\n\n\033[0m", (void*)((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP], (void*)process_heap_address);
}
else {
_native_in_isr = 1;
DEBUG("\n\033[31mEIP:\t%p\nHEAP:\t%p\ngo switching\n\n\033[0m", (void*)((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP], (void*)process_heap_address);
//printf("\n\033[31mEIP:\t%p\nHEAP:\t%p\ngo switching\n\n\033[0m", (void*)((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP], (void*)process_heap_address);
_native_saved_eip = ((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP];
((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP] = (unsigned int)&_native_sig_leave_tramp;
}
@ -515,13 +502,14 @@ void native_interrupt_init(void)
_native_in_syscall = 0;
if (pipe(pipefd) == -1) {
if (pipe(_sig_pipefd) == -1) {
err(1, "native_interrupt_init(): pipe()");
}
/* allow for ctrl+c to shut down gracefully */
register_interrupt(SIGINT, shutdown);
puts("RIOT native interrupts/signals initialized.");
}
/** @} */

11
cpu/native/lpm_cpu.c

@ -28,6 +28,8 @@
#include "lpm.h"
#include "debug.h"
#include "cpu.h"
#include "native_internal.h"
#ifdef MODULE_UART0
#include "board_internal.h"
#endif
@ -51,7 +53,10 @@ void _native_lpm_sleep()
nfds = _native_set_uart_fds();
nfds++;
_native_in_syscall++; // no switching here
nfds = select(nfds, &_native_rfds, NULL, NULL, NULL);
_native_in_syscall--;
DEBUG("_native_lpm_sleep: returned: %i\n", nfds);
if (nfds != -1) {
@ -71,9 +76,8 @@ void _native_lpm_sleep()
if (_native_sigpend > 0) {
DEBUG("\n\n\t\treturn from syscall, calling native_irq_handler\n\n");
_native_in_syscall = 0;
_native_in_isr = 1;
swapcontext(_native_cur_ctx, _native_isr_ctx);
_native_in_syscall++;
_native_syscall_leave();
}
}
@ -98,7 +102,6 @@ enum lpm_mode lpm_set(enum lpm_mode target)
case LPM_IDLE:
//DEBUG("lpm_set(): pause()\n");
_native_in_syscall = 1;
//pause();
_native_lpm_sleep();
break;

8
cpu/native/native_cpu.c

@ -42,12 +42,15 @@
#include "cpu.h"
#include "cpu-conf.h"
#include "native_internal.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
extern volatile tcb_t *active_thread;
static ucontext_t end_context;
static char __end_stack[SIGSTKSZ];
ucontext_t end_context;
char __end_stack[SIGSTKSZ];
#ifdef MODULE_UART0
fd_set _native_rfds;
@ -104,7 +107,6 @@ char *thread_stack_init(void (*task_func)(void), void *stack_start, int stacksiz
void cpu_switch_context_exit(void)
{
ucontext_t *ctx;
extern int native_interrupts_enabled;
DEBUG("XXX: cpu_switch_context_exit()\n");
if ((sched_context_switch_request == 1) || (active_thread == NULL)) {

5
cpu/native/net/tap.c

@ -44,6 +44,7 @@
#include "tap.h"
#include "nativenet.h"
#include "nativenet_internal.h"
#include "native_internal.h"
#define TAP_BUFFER_LENGTH (ETHER_MAX_LEN)
int _native_marshall_ethernet(uint8_t *framebuf, radio_packet_t *packet);
@ -62,9 +63,7 @@ void _native_handle_tap_input(void)
/* TODO: check whether this is an input or an output event
TODO: refactor this into general io-signal multiplexer */
_native_in_syscall = 1;
nread = read(_native_tap_fd, &frame, sizeof(union eth_frame));
_native_in_syscall = 0;
nread = real_read(_native_tap_fd, &frame, sizeof(union eth_frame));
DEBUG("_native_handle_tap_input - read %d bytes\n", nread);
if (nread > 0) {
if (ntohs(frame.field.header.ether_type) == NATIVE_ETH_PROTO) {

10
cpu/native/rtc/posix-rtc.c

@ -26,6 +26,8 @@
#include "rtc.h"
#include "cpu.h"
#include "native_internal.h"
static int native_rtc_enabled;
void rtc_init(void)
@ -59,24 +61,24 @@ void rtc_get_localtime(struct tm *localt)
time_t t;
if (native_rtc_enabled == 1) {
_native_in_syscall++;
_native_syscall_enter();
t = time(NULL);
if (localtime_r(&t, localt) == NULL) {
err(1, "rtc_get_localtime: localtime_r");
}
_native_in_syscall--;
_native_syscall_leave();
}
}
time_t rtc_time(struct timeval *time)
{
if (native_rtc_enabled == 1) {
_native_in_syscall++;
_native_syscall_enter();
if (gettimeofday(time, NULL) == -1) {
err(1, "rtc_time: gettimeofday");
}
_native_in_syscall--;
_native_syscall_leave();
}
return time->tv_sec;
}

20
cpu/native/startup.c

@ -14,21 +14,29 @@
* @}
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#include <dlfcn.h>
#else
#include <dlfcn.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <kernel_internal.h>
#include <cpu.h>
#include "tap.h"
#include "kernel_internal.h"
#include "cpu.h"
extern void board_init(void);
extern void native_cpu_init(void);
extern void native_interrupt_init(void);
#include "native_internal.h"
#include "tap.h"
__attribute__((constructor)) static void startup(int argc, char **argv)
{
/* get system read/write */
*(void **)(&real_read) = dlsym(RTLD_NEXT, "read");
*(void **)(&real_write) = dlsym(RTLD_NEXT, "write");
#ifdef MODULE_NATIVENET
if (argc < 2) {

154
cpu/native/syscalls.c

@ -0,0 +1,154 @@
/**
* Native CPU syscall managing
*
* Wrap system calls and system call invoking library calls to make
* sure no context switches happen during a system call.
*
* Copyright (C) 2013 Ludwig Ortmann
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup native_cpu
* @{
* @file
* @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#include <dlfcn.h>
#else
#include <dlfcn.h>
#endif
#include <err.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include "cpu.h"
#include "native_internal.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
extern volatile tcb_t *active_thread;
ssize_t (*real_read)(int fd, void *buf, size_t count);
ssize_t (*real_write)(int fd, const void *buf, size_t count);
void _native_syscall_enter()
{
_native_in_syscall++;
DEBUG("> _native_in_syscall: %d\n", _native_in_syscall);
}
void _native_syscall_leave()
{
_native_in_syscall--;
DEBUG("< _native_in_syscall: %d\n", _native_in_syscall);
if ((_native_sigpend > 0) && (_native_in_isr == 0) && (_native_in_syscall == 0)) {
_native_in_isr = 1;
_native_cur_ctx = (ucontext_t *)active_thread->sp;
makecontext(&native_isr_context, native_irq_handler, 0);
swapcontext(_native_cur_ctx, &native_isr_context);
}
}
ssize_t read(int fd, void *buf, size_t count)
{
ssize_t r;
_native_syscall_enter();
r = real_read(fd, buf, count);
_native_syscall_leave();
return r;
}
ssize_t write(int fd, const void *buf, size_t count)
{
ssize_t r;
_native_syscall_enter();
//real_write(fd, "real_write: ", 12);
r = real_write(fd, buf, count);
_native_syscall_leave();
return r;
}
int putchar(int c) {
write(STDOUT_FILENO, &c, 1);
return 0;
}
int puts(const char *s)
{
int r;
r = write(STDOUT_FILENO, (char*)s, strlen(s));
putchar('\n');
return r;
}
char *make_message(const char *format, va_list argp)
{
int n;
int size = 100;
char *message, *temp;
if ((message = malloc(size)) == NULL)
return NULL;
while (1) {
n = vsnprintf(message, size, format, argp);
if (n < 0)
return NULL;
if (n < size)
return message;
size = n + 1;
if ((temp = realloc(message, size)) == NULL) {
free(message);
return NULL;
} else {
message = temp;
}
}
}
int printf(const char *format, ...)
{
int r;
va_list argp;
char *m;
va_start(argp, format);
if ((m = make_message(format, argp)) == NULL) {
err(EXIT_FAILURE, "malloc");
}
r = write(STDOUT_FILENO, m, strlen(m));
va_end(argp);
free(m);
return r;
}
int vprintf(const char *format, va_list argp)
{
int r;
char *m;
if ((m = make_message(format, argp)) == NULL) {
err(EXIT_FAILURE, "malloc");
}
r = write(STDOUT_FILENO, m, strlen(m));
free(m);
return r;
}
Loading…
Cancel
Save