#include "api/error.h" #include "boot/initrd.h" #include "lib/printf.h" #include "sys/message.h" #include "sys/syscall.h" #include "lib/string.h" int s_syscall_initrd_file_name( jove_owned_obj_t *initrd_file, jove_owned_obj_t *message, void *message_data) { const char *filename = initrd_file_name(initrd_file); size_t filename_len = strlen(filename); size_t bytes_left = 0x1000; size_t bytes_needed = filename_len + sizeof(struct syscall_initrd_file_name_ret); CHECK_TOOSMALL(bytes_needed, bytes_left, "Message is too small for file name."); struct syscall_initrd_file_name_ret *payload = message_data; payload->len = filename_len; memcpy(payload->c_str, filename, filename_len); return 0; } int s_syscall_initrd_file_size(jove_owned_obj_t *initrd_file) { return initrd_file_size(initrd_file); } int s_syscall_initrd_file_read( jove_owned_obj_t *initrd_file, jove_owned_obj_t *message, void *message_data, size_t bytes_left, void *payload_data) { //Ensure that the message payload could hold the required read payload. size_t bytes_needed = sizeof(struct syscall_initrd_file_read); CHECK_TOOSMALL(bytes_needed, bytes_left, "Message is too small to hold read payload."); struct syscall_initrd_file_read *payload = payload_data; bytes_needed = payload->read_size; bytes_left = 0x1000; //Ensure that the message is big enough to hold the read file data. CHECK_TOOSMALL(bytes_needed, bytes_left, "Message is too small to hold read bytes."); size_t file_size = initrd_file_size(initrd_file); char *file_data = initrd_file_data(initrd_file); //Ensure that the start index is within the file. if(payload->start_index >= file_size) { klogf("Start index exceeds file length! (%i > %i)\n", payload->start_index, file_size); return -EOOB; } //Ensure that the read bounds is within the file. if(payload->start_index + payload->read_size > file_size) { klogf("Read bounds exceed file length! (%i+%i > %i)\n", payload->start_index, payload->read_size, file_size); return -ETOOBIG; } memcpy(message_data, file_data + payload->start_index, payload->read_size); return 0; } int _syscall_handle_initrd_file(syscall_context_t *ctx) { switch(ctx->header->callid) { case SYSCALL_INITRD_FILE_NAME: if(ctx->target.permissions & SYSCALL_PERM_INITRD_FILE_NAME) return s_syscall_initrd_file_name( ctx->target.obj, ctx->message.obj, (void*)ctx->header); return -EPERM; case SYSCALL_INITRD_FILE_SIZE: if(ctx->target.permissions & SYSCALL_PERM_INITRD_FILE_SIZE) return s_syscall_initrd_file_size(ctx->target.obj); return -EPERM; case SYSCALL_INITRD_FILE_READ: if(ctx->target.permissions & SYSCALL_PERM_INITRD_FILE_READ) return s_syscall_initrd_file_read( ctx->target.obj, ctx->message.obj, (void*)ctx->header, ctx->bytes_left, ctx->payload); return -EPERM; default: return -EBADCALL; } }