auxv.c revision 331722
1/*- 2 * Copyright 2010, 2012 Konstantin Belousov <kib@FreeBSD.ORG>. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: stable/11/lib/libc/gen/auxv.c 331722 2018-03-29 02:50:57Z eadler $"); 29 30#include "namespace.h" 31#include <elf.h> 32#include <errno.h> 33#include <link.h> 34#include <pthread.h> 35#include <string.h> 36#include "un-namespace.h" 37#include "libc_private.h" 38 39extern char **environ; 40extern int _DYNAMIC; 41#pragma weak _DYNAMIC 42 43void *__elf_aux_vector; 44static pthread_once_t aux_vector_once = PTHREAD_ONCE_INIT; 45 46static void 47init_aux_vector_once(void) 48{ 49 Elf_Addr *sp; 50 51 sp = (Elf_Addr *)environ; 52 while (*sp++ != 0) 53 ; 54 __elf_aux_vector = (Elf_Auxinfo *)sp; 55} 56 57void 58__init_elf_aux_vector(void) 59{ 60 61 if (&_DYNAMIC != NULL) 62 return; 63 _once(&aux_vector_once, init_aux_vector_once); 64} 65 66static pthread_once_t aux_once = PTHREAD_ONCE_INIT; 67static int pagesize, osreldate, canary_len, ncpus, pagesizes_len; 68static char *canary, *pagesizes; 69static void *timekeep; 70 71static void 72init_aux(void) 73{ 74 Elf_Auxinfo *aux; 75 76 for (aux = __elf_aux_vector; aux->a_type != AT_NULL; aux++) { 77 switch (aux->a_type) { 78 case AT_CANARY: 79 canary = (char *)(aux->a_un.a_ptr); 80 break; 81 82 case AT_CANARYLEN: 83 canary_len = aux->a_un.a_val; 84 break; 85 86 case AT_PAGESIZES: 87 pagesizes = (char *)(aux->a_un.a_ptr); 88 break; 89 90 case AT_PAGESIZESLEN: 91 pagesizes_len = aux->a_un.a_val; 92 break; 93 94 case AT_PAGESZ: 95 pagesize = aux->a_un.a_val; 96 break; 97 98 case AT_OSRELDATE: 99 osreldate = aux->a_un.a_val; 100 break; 101 102 case AT_NCPUS: 103 ncpus = aux->a_un.a_val; 104 break; 105 106 case AT_TIMEKEEP: 107 timekeep = aux->a_un.a_ptr; 108 break; 109 } 110 } 111} 112 113int 114_elf_aux_info(int aux, void *buf, int buflen) 115{ 116 int res; 117 118 __init_elf_aux_vector(); 119 if (__elf_aux_vector == NULL) 120 return (ENOSYS); 121 _once(&aux_once, init_aux); 122 123 switch (aux) { 124 case AT_CANARY: 125 if (canary != NULL && canary_len >= buflen) { 126 memcpy(buf, canary, buflen); 127 memset(canary, 0, canary_len); 128 canary = NULL; 129 res = 0; 130 } else 131 res = ENOENT; 132 break; 133 case AT_PAGESIZES: 134 if (pagesizes != NULL && pagesizes_len >= buflen) { 135 memcpy(buf, pagesizes, buflen); 136 res = 0; 137 } else 138 res = ENOENT; 139 break; 140 141 case AT_PAGESZ: 142 if (buflen == sizeof(int)) { 143 if (pagesize != 0) { 144 *(int *)buf = pagesize; 145 res = 0; 146 } else 147 res = ENOENT; 148 } else 149 res = EINVAL; 150 break; 151 case AT_OSRELDATE: 152 if (buflen == sizeof(int)) { 153 if (osreldate != 0) { 154 *(int *)buf = osreldate; 155 res = 0; 156 } else 157 res = ENOENT; 158 } else 159 res = EINVAL; 160 break; 161 case AT_NCPUS: 162 if (buflen == sizeof(int)) { 163 if (ncpus != 0) { 164 *(int *)buf = ncpus; 165 res = 0; 166 } else 167 res = ENOENT; 168 } else 169 res = EINVAL; 170 break; 171 case AT_TIMEKEEP: 172 if (buflen == sizeof(void *)) { 173 if (timekeep != NULL) { 174 *(void **)buf = timekeep; 175 res = 0; 176 } else 177 res = ENOENT; 178 } else 179 res = EINVAL; 180 break; 181 default: 182 res = ENOENT; 183 break; 184 } 185 return (res); 186} 187