X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/ba6e6b64033b1f9de49feccb5c9cd438354481f7..0f00dc4c8eb47e67bc0f148c2dd109f73a451e0a:/lmem.c diff --git a/lmem.c b/lmem.c deleted file mode 100644 index a7033d0..0000000 --- a/lmem.c +++ /dev/null @@ -1,346 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Locked memory allocation (Unix-specific) - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#include "config.h" - -#include -#include -#include -#include -#include - -#include -#include - -#ifdef HAVE_MLOCK -# include -#endif - -#include -#include -#include - -#include "lmem.h" - -/*----- Arena operations --------------------------------------------------*/ - -static void *aalloc(arena *a, size_t sz) { return l_alloc((lmem *)a, sz); } -static void afree(arena *a, void *p) { l_free((lmem *)a, p); } -static void apurge(arena *a) { l_purge((lmem *)a); } - -static const arena_ops l_ops = { aalloc, arena_fakerealloc, afree, apurge }; - -/*----- Main code ---------------------------------------------------------*/ - -/* --- @l_init@ --- * - * - * Arguments: @lmem *lm@ = pointer to locked memory descriptor - * @size_t sz@ = size of locked memory area requested - * - * Returns: Zero if everything is fine, @+1@ if some insecure memory was - * allocated, and @-1@ if everything went horribly wrong. - * - * Use: Initializes the locked memory manager. This function is safe - * to call in a privileged program; privileges should usually be - * dropped after allocating the locked memory block. - * - * You must call @sub_init@ before allocating locked memory - * buffers. - */ - -int l_init(lmem *lm, size_t sz) -{ - char *p; - int rc = 0; - l_node *l; - - /* --- Preliminaries --- */ - - lm->a.ops = &l_ops; - lm->err = 0; - lm->f = 0; - - /* --- Try making a secure locked passphrase buffer --- * - * - * Drop privileges before emitting diagnostic messages. - */ - -#ifdef HAVE_MLOCK - - /* --- Memory-map a page from somewhere --- */ - -# ifdef MAP_ANON - p = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); -# else - { - int fd; - if ((fd = open("/dev/zero", O_RDWR)) >= 0) { - p = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - close(fd); - } - } -# endif - - /* --- Lock the page in memory --- * - * - * Why does @mmap@ return such a stupid result if it fails? - */ - - if (p == 0 || p == MAP_FAILED) { - lm->emsg = "couldn't map locked memory area: %s"; - lm->err = errno; - p = 0; - } else if (mlock(p, sz)) { - lm->emsg = "error locking memory area: %s"; - lm->err = errno; - munmap(p, sz); - p = 0; - } else - lm->f |= LF_LOCKED; - -#endif - - /* --- Make a standard passphrase buffer --- */ - -#ifdef HAVE_MLOCK - if (!p) -#else - lm->err = 0; - lm->emsg = "locked memory not available on this system"; -#endif - { - if ((p = malloc(sz)) == 0) { - lm->emsg = "not enough standard memory!"; - lm->err = ENOMEM; - return (-1); - } - rc = +1; - } - - /* --- Initialize the buffer --- */ - - lm->sz = lm->free = sz; - lm->p = p; - - /* --- Initialize the free list --- */ - - l = CREATE(l_node); - l->next = 0; - l->p = p; - l->sz = sz; - l->f = 0; - lm->l = l; - - /* --- Done --- */ - - return (rc); -} - -/* --- @l_alloc@ --- * - * - * Arguments: @lmem *lm@ = pointer to locked memory descriptor - * @size_t sz@ = size requested - * - * Returns: Pointer to allocated memory. - * - * Use: Allocates @sz@ bytes of locked memory. - */ - -void *l_alloc(lmem *lm, size_t sz) -{ - l_node *l; - - sz = (sz + 3u) & ~3u; - for (l = lm->l; l; l = l->next) { - if (l->f & LF_ALLOC) - continue; - if (l->sz < sz) - continue; - l->f |= LF_ALLOC; - if (l->sz > sz) { - l_node *n = CREATE(l_node); - n->next = l->next; - n->p = l->p + sz; - n->sz = l->sz - sz; - l->sz = sz; - n->f = 0; - l->next = n; - } - assert(((void)"Locked buffer space has vanished", lm->free >= sz)); - lm->free -= sz; - return (l->p); - } - return (0); -} - -/* --- @l_free@ --- * - * - * Arguments: @lmem *lm@ = pointer to locked memory descriptor - * @void *p@ = pointer to block - * - * Returns: --- - * - * Use: Releases a block of locked memory. - */ - -void l_free(lmem *lm, void *p) -{ - l_node *l; - l_node *ll = 0; - - for (l = lm->l; l; l = l->next) { - size_t sz; - - /* --- If this isn't the block, skip it --- */ - - if (l->p != p) { - ll = l; - continue; - } - assert(((void)"Block is already free", l->f & LF_ALLOC)); - - /* --- Coalesce with adjacent free blocks --- */ - - l->f &= ~LF_ALLOC; - sz = l->sz; - memset(p, 0, sz); - - if (ll && !(ll->f & LF_ALLOC)) { - assert(((void)"Previous block doesn't fit", ll->p + ll->sz == p)); - ll->sz += sz; - ll->next = l->next; - DESTROY(l); - l = ll; - } - - ll = l->next; - if (ll && !(ll->f & LF_ALLOC)) { - assert(((void)"Next block doesn't fit", ll->p == l->p + l->sz)); - l->sz += ll->sz; - l->next = ll->next; - DESTROY(ll); - } - - lm->free += sz; - assert(((void)"Free lunch", lm->free <= lm->sz)); - return; - } - assert(((void)"Not a locked block", 0)); -} - -/* --- @l_purge@ --- * - * - * Arguments: @lmem *lm@ = pointer to locked memory descriptor - * - * Returns: --- - * - * Use: Purges all the free blocks in the buffer, and clears all of - * the locked memory. Memory is not freed back to the system. - */ - -void l_purge(lmem *lm) -{ - l_node *l; - - l = lm->l; - while (l) { - l_node *ll = l->next; - DESTROY(l); - l = ll; - } - memset(lm->p, 0, lm->sz); - l = CREATE(l_node); - l->next = 0; - l->p = lm->p; - l->sz = lm->sz; - l->f = 0; - lm->l = l; - lm->free = l->sz; -} - -/* --- @l_destroy@ --- * - * - * Arguments: @lmem *lm@ = pointer to locked memory descriptor - * - * Returns: --- - * - * Use: Disposes of a locked memory arena permanently. - */ - -void l_destroy(lmem *lm) -{ - l_node *l; - - l = lm->l; - while (l) { - l_node *ll = l->next; - DESTROY(l); - l = ll; - } - memset(lm->p, 0, lm->sz); - -#ifdef HAVE_MLOCK - if (lm->f & LF_LOCKED) - munmap(lm->p, lm->sz); - else -#endif - free(lm->p); /*sic*/ -} - -/* --- @l_report@ --- * - * - * Arguments: @lmem *lm@ = pointer to locked memory descriptor - * @dstr *d@ = string to write the error message on - * - * Returns: Zero if the buffer is fine, @+1@ if there was a problem - * getting locked memory but insecure stuff could be allocated, - * and @-1@ if not even insecure memory could be found. - * - * Use: Returns a user-digestable explanation for the state of a - * locked memory buffer. If the return code is zero, no message - * is emitted to the string @d@. - */ - -int l_report(lmem *lm, dstr *d) -{ - int rc; - if (lm->err) - dstr_putf(d, lm->emsg, strerror(lm->err)); - if (!lm->p) - rc = -1; - else if (lm->err) - rc = +1; - else - rc = 0; - return (rc); -} - -/*----- That's all, folks -------------------------------------------------*/