1/* 2 * This program is free software; you can redistribute it and/or 3 * modify it under the terms of the GNU General Public License as 4 * published by the Free Software Foundation; either version 2 of 5 * the License, or (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, write to the Free Software 14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 15 * MA 02111-1307 USA 16 */ 17/* 18 * Part of Very Secure FTPd 19 * Licence: GPL v2 20 * Author: Chris Evans 21 * secbuf.c 22 * 23 * Here are some routines providing the (possibly silly) concept of a secure 24 * buffer. A secure buffer may not be overflowed. A single byte overflow 25 * will cause the program to safely terminate. 26 */ 27 28#include "secbuf.h" 29#include "utility.h" 30#include "sysutil.h" 31#include "sysdeputil.h" 32 33void 34vsf_secbuf_alloc(char** p_ptr, unsigned int size) 35{ 36 unsigned int page_offset; 37 unsigned int round_up; 38 char* p_mmap; 39 char* p_no_access_page; 40 unsigned int page_size = vsf_sysutil_getpagesize(); 41 42 /* Free any previous buffer */ 43 vsf_secbuf_free(p_ptr); 44 /* Round up to next page size */ 45 page_offset = size % page_size; 46 if (page_offset) 47 { 48 unsigned int num_pages = size / page_size; 49 num_pages++; 50 round_up = num_pages * page_size; 51 } 52 else 53 { 54 /* Allocation is on a page-size boundary */ 55 round_up = size; 56 } 57 /* Add on another two pages to make inaccessible */ 58 round_up += page_size * 2; 59 60 p_mmap = vsf_sysutil_map_anon_pages(round_up); 61 /* Map the first and last page inaccessible */ 62 p_no_access_page = p_mmap + round_up - page_size; 63 vsf_sysutil_memprotect(p_no_access_page, page_size, kVSFSysUtilMapProtNone); 64 /* Before we make the "before" page inaccessible, store the size in it. 65 * A little hack so that we don't need to explicitly be passed the size 66 * when freeing an existing secure buffer 67 */ 68 *((unsigned int*)p_mmap) = round_up; 69 p_no_access_page = p_mmap; 70 vsf_sysutil_memprotect(p_no_access_page, page_size, kVSFSysUtilMapProtNone); 71 72 p_mmap += page_size; 73 if (page_offset) 74 { 75 p_mmap += (page_size - page_offset); 76 } 77 *p_ptr = p_mmap; 78} 79 80void 81vsf_secbuf_free(char** p_ptr) 82{ 83 unsigned int map_size; 84 unsigned long page_offset; 85 char* p_mmap = *p_ptr; 86 unsigned int page_size = vsf_sysutil_getpagesize(); 87 if (p_mmap == 0) 88 { 89 return; 90 } 91 /* Calculate the actual start of the mmap region */ 92 page_offset = (unsigned long) p_mmap % page_size; 93 if (page_offset) 94 { 95 p_mmap -= page_offset; 96 } 97 p_mmap -= page_size; 98 /* First make the first page readable so we can get the size */ 99 vsf_sysutil_memprotect(p_mmap, page_size, kVSFSysUtilMapProtReadOnly); 100 /* Extract the mapping size */ 101 map_size = *((unsigned int*)p_mmap); 102 /* Lose the mapping */ 103 vsf_sysutil_memunmap(p_mmap, map_size); 104} 105 106