From 196bb3b684a23b88291fd257812f066e4ff381dd Mon Sep 17 00:00:00 2001 From: Scott Haseley Date: Mon, 7 Mar 2016 15:05:58 -0500 Subject: [PATCH] Now using static buffers (and protecting with a semaphore) for kernel secprintf. We have to do this because we need secure output in kmalloc. --- common/libtest161/secure.c | 15 ++-------- common/libtest161/test161.c | 60 +++++++++++++++++++++++++++---------- kern/include/kern/test161.h | 4 +++ kern/main/main.c | 2 ++ 4 files changed, 53 insertions(+), 28 deletions(-) diff --git a/common/libtest161/secure.c b/common/libtest161/secure.c index eb02485..a44086f 100644 --- a/common/libtest161/secure.c +++ b/common/libtest161/secure.c @@ -44,35 +44,25 @@ static int did_random = 0; #define MSEC_PER_SEC 1000ULL #endif +// Both userspace and the kernel are using the temp buffers now. static void * _alloc(size_t size) { -#ifdef _KERNEL - // Compiler - (void)temp_buffers; - (void)buf_num; - - return kmalloc(size); -#else (void)size; void *ptr = temp_buffers[buf_num]; buf_num++; buf_num = buf_num % NUM_BUFFERS; return ptr; -#endif } static void _free(void *ptr) { -#ifdef _KERNEL - kfree(ptr); -#else (void)ptr; -#endif } /* * hamc_sha256 follows FIPS 198-1 HMAC using sha256. * See http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf for details. + * NOTE: This is only thread-safe if called from within secprintf()!!! */ static int hmac_sha256(const char *msg, size_t msg_len, const char *key, size_t key_len, unsigned char output[SHA256_OUTPUT_SIZE]) @@ -189,6 +179,7 @@ int hmac(const char *msg, size_t msg_len, const char *key, size_t key_len, return 0; } +// NOTE: This is only thread-safe if called from within secprintf()!!! int hmac_salted(const char *msg, size_t msg_len, const char *key, size_t key_len, char **hash_str, char **salt_str) { diff --git a/common/libtest161/test161.c b/common/libtest161/test161.c index 305313d..0b07a9d 100644 --- a/common/libtest161/test161.c +++ b/common/libtest161/test161.c @@ -3,6 +3,7 @@ #ifdef _KERNEL #include #include +#include #include #include #include @@ -17,31 +18,32 @@ #include #endif -// Hack for allocating userspace memory without malloc. -#define BUFFER_SIZE 4096 +// Hack for allocating userspace memory without malloc, and for +// allowing secprintf in kmalloc when we're out of memory. +#define BUFFER_SIZE 1024 + +static char temp_buffer[BUFFER_SIZE]; #ifndef _KERNEL -static char temp_buffer[BUFFER_SIZE]; static char write_buffer[BUFFER_SIZE]; #endif -static inline void * _alloc(size_t size) -{ #ifdef _KERNEL - return kmalloc(size); -#else - (void)size; - return temp_buffer; +// secprintf needs to be synchronized in the kernel because multiple threads +// may be trying to secprintf at the same time. +static struct semaphore *test161_sem; #endif + +// For now, allocating just passes a reference to our static temp buffer, and +// free does nothing. +static inline void * _alloc() +{ + return temp_buffer; } static inline void _free(void *ptr) { -#ifdef _KERNEL - kfree(ptr); -#else (void)ptr; -#endif } /* @@ -106,19 +108,29 @@ secprintf(const char * secret, const char * msg, const char * name) int res; size_t len; +#ifdef _KERNEL + if (test161_sem == NULL) { + panic("test161_sem is NULL. Your kernel is missing test161_bootstrap."); + } + P(test161_sem); +#endif + hash = salt = fullmsg = NULL; // test161 expects "name: msg" len = strlen(name) + strlen(msg) + 3; // +3 for " :" and null terminator fullmsg = (char *)_alloc(len); if (fullmsg == NULL) { - return -ENOMEM; + res = -ENOMEM; + goto out; } snprintf(fullmsg, len, "%s: %s", name, msg); res = hmac_salted(fullmsg, len-1, secret, strlen(secret), &hash, &salt); - if (res) - return -res; + if (res) { + res = -res; + goto out; + } #ifdef _KERNEL res = kprintf("(%s, %s, %s, %s: %s)\n", name, hash, salt, name, msg); @@ -126,11 +138,27 @@ secprintf(const char * secret, const char * msg, const char * name) res = say("(%s, %s, %s, %s: %s)\n", name, hash, salt, name, msg); #endif +out: + // These may be NULL, but that's OK _free(hash); _free(salt); _free(fullmsg); +#ifdef _KERNEL + V(test161_sem); +#endif + return res; } #endif + +#ifdef _KERNEL +void test161_bootstrap() +{ + test161_sem = sem_create("test161", 1); + if (test161_sem == NULL) { + panic("Failed to create test161 secprintf semaphore"); + } +} +#endif diff --git a/kern/include/kern/test161.h b/kern/include/kern/test161.h index e159e13..096384b 100644 --- a/kern/include/kern/test161.h +++ b/kern/include/kern/test161.h @@ -39,4 +39,8 @@ int success(int, const char *, const char *); int secprintf(const char *secret, const char *msg, const char *name); int partial_credit(const char *secret, const char *name, int scored, int total); +#ifdef _KERNEL +void test161_bootstrap(void); +#endif + #endif /* _KERN_TEST161_H_ */ diff --git a/kern/main/main.c b/kern/main/main.c index d095480..715ef99 100644 --- a/kern/main/main.c +++ b/kern/main/main.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include "autoconf.h" // for pseudoconfig @@ -127,6 +128,7 @@ boot(void) vm_bootstrap(); kprintf_bootstrap(); thread_start_cpus(); + test161_bootstrap(); /* Default bootfs - but ignore failure, in case emu0 doesn't exist */ vfs_setbootfs("emu0");