1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13#include <autoconf.h> 14#include <sel4camkes/gen_config.h> 15#include <assert.h> 16#include <errno.h> 17#include <fcntl.h> 18#include <limits.h> 19#include <stdarg.h> 20#include <string.h> 21#include <stdio.h> 22#include <stdlib.h> 23#include <unistd.h> 24 25#include <sel4/sel4.h> 26 27#include <sys/resource.h> 28#include <sys/mman.h> 29#include <sys/uio.h> 30 31#include <sys/types.h> 32#include <sys/socket.h> 33#include <bits/syscall.h> 34#include <muslcsys/vsyscall.h> 35#include <muslcsys/io.h> 36 37#include <sel4utils/util.h> 38 39#include "sys_io.h" 40 41static muslcsys_syscall_t original_sys_close = NULL; 42static muslcsys_syscall_t original_sys_read = NULL; 43static muslcsys_syscall_t original_sys_write = NULL; 44 45int sock_close(int fd) __attribute__((weak)); 46static long camkes_sys_close(va_list ap) 47{ 48 va_list copy; 49 va_copy(copy, ap); 50 int fd = va_arg(ap, int); 51 if (sock_close && valid_fd(fd)) { 52 muslcsys_fd_t *fds = get_fd_struct(fd); 53 if (fds->filetype == FILE_TYPE_SOCKET) { 54 sock_close(*(int *)fds->data); 55 } 56 } 57 long ret; 58 if (original_sys_close) { 59 ret = original_sys_close(copy); 60 } else { 61 ret = -ENOSYS; 62 } 63 va_end(copy); 64 return ret; 65} 66 67int sock_write(int sockfd, int count) __attribute__((weak)); 68static long camkes_sys_write(va_list ap) 69{ 70 va_list copy; 71 va_copy(copy, ap); 72 int fd = va_arg(ap, int); 73 void *buf = va_arg(ap, void *); 74 size_t count = va_arg(ap, size_t); 75 76 if (sock_write && sock_data && valid_fd(fd)) { 77 muslcsys_fd_t *fds = get_fd_struct(fd); 78 if (fds->filetype == FILE_TYPE_SOCKET) { 79 int sockfd = *(int *)fds->data; 80 ssize_t size = count > PAGE_SIZE_4K ? PAGE_SIZE_4K : count; 81 memcpy((char *)sock_data, buf, size); 82 return sock_write(sockfd, size); 83 } 84 } 85 long ret; 86 if (original_sys_write) { 87 ret = original_sys_write(copy); 88 } else { 89 // redirect to writev as a last resort 90 struct iovec io; 91 io.iov_base = buf; 92 io.iov_len = count; 93 ret = writev(fd, &io, 1); 94 // as the syscall implementation we expect to return the error directly and have 95 // our caller set errno or not. writev, however, is documented as putting its error 96 // code in errno. So if writev returns an error we need to get the error out of errno 97 // and return it up, so that it can ultimately get put back into errno 98 if (ret == -1) { 99 ret = errno; 100 } 101 } 102 va_end(copy); 103 return ret; 104} 105 106int sock_read(int sockfd, int count) __attribute__((weak)); 107static long camkes_sys_read(va_list ap) 108{ 109 va_list copy; 110 va_copy(copy, ap); 111 int fd = va_arg(ap, int); 112 void *buf = va_arg(ap, void *); 113 size_t count = va_arg(ap, size_t); 114 if (sock_read && sock_data && valid_fd(fd)) { 115 muslcsys_fd_t *fds = get_fd_struct(fd); 116 if (fds->filetype == FILE_TYPE_SOCKET) { 117 int sockfd = *(int *)fds->data; 118 int size = count > PAGE_SIZE_4K ? PAGE_SIZE_4K : count; 119 int ret = sock_read(sockfd, size); 120 memcpy(buf, (char *)sock_data, ret); 121 return ret; 122 } 123 } 124 long ret; 125 if (original_sys_read) { 126 ret = original_sys_read(copy); 127 } else { 128 ret = -ENOSYS; 129 } 130 va_end(copy); 131 return ret; 132} 133 134int sock_fcntl(int sockfd, int cmd, int val) __attribute__((weak)); 135static long UNUSED camkes_sys_fcntl64(va_list ap) 136{ 137 int fd = va_arg(ap, int); 138 int cmd = va_arg(ap, int); 139 140 int sockfd; 141 muslcsys_fd_t *fdt = get_fd_struct(fd); 142 if (fdt->filetype == FILE_TYPE_SOCKET && sock_fcntl) { 143 sockfd = *(int *)fdt->data; 144 long val = va_arg(ap, long); 145 return sock_fcntl(sockfd, cmd, val); 146 } 147 148 assert(!"sys_fcntl64 not implemented"); 149 return -EINVAL; 150} 151 152void camkes_install_io_syscalls() 153{ 154 original_sys_close = muslcsys_install_syscall(__NR_close, camkes_sys_close); 155 assert(original_sys_close); 156 original_sys_read = muslcsys_install_syscall(__NR_read, camkes_sys_read); 157 assert(original_sys_read); 158 original_sys_write = muslcsys_install_syscall(__NR_write, camkes_sys_write); 159#ifdef __NR_fcntl64 160 muslcsys_install_syscall(__NR_fcntl64, camkes_sys_fcntl64); 161#endif 162} 163