summaryrefslogtreecommitdiffstats
path: root/lib/libc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/gen/Makefile.inc2
-rw-r--r--lib/libc/gen/Symbol.map2
-rw-r--r--lib/libc/gen/__getosreldate.c9
-rw-r--r--lib/libc/gen/aux.c146
-rw-r--r--lib/libc/gen/getosreldate.c9
-rw-r--r--lib/libc/gen/getpagesize.c25
-rw-r--r--lib/libc/gen/getpagesizes.c13
-rw-r--r--lib/libc/include/libc_private.h2
-rw-r--r--lib/libc/stdlib/malloc.c23
-rw-r--r--lib/libc/sys/stack_protector.c8
10 files changed, 217 insertions, 22 deletions
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
index 0db5911..2c3d392 100644
--- a/lib/libc/gen/Makefile.inc
+++ b/lib/libc/gen/Makefile.inc
@@ -7,7 +7,7 @@
SRCS+= __getosreldate.c __xuname.c \
_once_stub.c _pthread_stubs.c _rand48.c _spinlock_stub.c \
_thread_init.c \
- alarm.c arc4random.c assert.c basename.c check_utility_compat.c \
+ alarm.c arc4random.c assert.c aux.c basename.c check_utility_compat.c \
clock.c closedir.c confstr.c \
crypt.c ctermid.c daemon.c devname.c dirname.c disklabel.c \
dlfcn.c drand48.c erand48.c err.c errlst.c errno.c \
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
index 42404bc..5ba1860 100644
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -492,4 +492,6 @@ FBSDprivate_1.0 {
_libc_sem_timedwait_compat;
_libc_sem_post_compat;
_libc_sem_getvalue_compat;
+
+ __elf_aux_vector;
};
diff --git a/lib/libc/gen/__getosreldate.c b/lib/libc/gen/__getosreldate.c
index 7e26845..980f9ef 100644
--- a/lib/libc/gen/__getosreldate.c
+++ b/lib/libc/gen/__getosreldate.c
@@ -29,6 +29,9 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/sysctl.h>
+#include <errno.h>
+#include <link.h>
+#include "libc_private.h"
int __getosreldate(void);
@@ -51,7 +54,11 @@ __getosreldate(void)
if (osreldate != 0)
return (osreldate);
-
+
+ error = _elf_aux_info(AT_OSRELDATE, &osreldate, sizeof(osreldate));
+ if (error == 0 && osreldate != 0)
+ return (osreldate);
+
oid[0] = CTL_KERN;
oid[1] = KERN_OSRELDATE;
osrel = 0;
diff --git a/lib/libc/gen/aux.c b/lib/libc/gen/aux.c
new file mode 100644
index 0000000..b5c079b
--- /dev/null
+++ b/lib/libc/gen/aux.c
@@ -0,0 +1,146 @@
+/*-
+ * Copyright 2010 Konstantin Belousov <kib@FreeBSD.ORG>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <elf.h>
+#include <errno.h>
+#include <link.h>
+#include <pthread.h>
+#include <string.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+Elf_Auxinfo *__elf_aux_vector;
+
+static pthread_once_t aux_once = PTHREAD_ONCE_INIT;
+
+static int pagesize, osreldate, canary_len, ncpus, pagesizes_len;
+static char *canary, *pagesizes;
+
+static void
+init_aux(void)
+{
+ Elf_Auxinfo *aux;
+
+ for (aux = __elf_aux_vector; aux->a_type != AT_NULL; aux++) {
+ switch (aux->a_type) {
+ case AT_CANARY:
+ canary = (char *)(aux->a_un.a_ptr);
+ break;
+
+ case AT_CANARYLEN:
+ canary_len = aux->a_un.a_val;
+ break;
+
+ case AT_PAGESIZES:
+ pagesizes = (char *)(aux->a_un.a_ptr);
+ break;
+
+ case AT_PAGESIZESLEN:
+ pagesizes_len = aux->a_un.a_val;
+ break;
+
+ case AT_PAGESZ:
+ pagesize = aux->a_un.a_val;
+ break;
+
+ case AT_OSRELDATE:
+ osreldate = aux->a_un.a_val;
+ break;
+
+ case AT_NCPUS:
+ ncpus = aux->a_un.a_val;
+ break;
+ }
+ }
+}
+
+int
+_elf_aux_info(int aux, void *buf, int buflen)
+{
+ int res;
+
+ if (__elf_aux_vector == NULL)
+ return (ENOSYS);
+ _once(&aux_once, init_aux);
+
+ switch (aux) {
+ case AT_CANARY:
+ if (canary != NULL && canary_len >= buflen) {
+ memcpy(buf, canary, buflen);
+ memset(canary, 0, canary_len);
+ canary = NULL;
+ res = 0;
+ } else
+ res = ENOENT;
+ break;
+ case AT_PAGESIZES:
+ if (pagesizes != NULL && pagesizes_len >= buflen) {
+ memcpy(buf, pagesizes, buflen);
+ res = 0;
+ } else
+ res = ENOENT;
+ break;
+
+ case AT_PAGESZ:
+ if (buflen == sizeof(int)) {
+ if (pagesize != 0) {
+ *(int *)buf = pagesize;
+ res = 0;
+ } else
+ res = ENOENT;
+ } else
+ res = EINVAL;
+ break;
+ case AT_OSRELDATE:
+ if (buflen == sizeof(int)) {
+ if (osreldate != 0) {
+ *(int *)buf = osreldate;
+ res = 0;
+ } else
+ res = ENOENT;
+ } else
+ res = EINVAL;
+ break;
+ case AT_NCPUS:
+ if (buflen == sizeof(int)) {
+ if (ncpus != 0) {
+ *(int *)buf = ncpus;
+ res = 0;
+ } else
+ res = ENOENT;
+ } else
+ res = EINVAL;
+ break;
+ default:
+ res = ENOENT;
+ break;
+ }
+ return (res);
+}
diff --git a/lib/libc/gen/getosreldate.c b/lib/libc/gen/getosreldate.c
index 086da6a..83bdc85 100644
--- a/lib/libc/gen/getosreldate.c
+++ b/lib/libc/gen/getosreldate.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/sysctl.h>
+#include <errno.h>
#include <stdlib.h>
#include <osreldate.h>
@@ -45,15 +46,17 @@ getosreldate(void)
int mib[2];
size_t size;
int value;
-
char *temp;
+ if ((temp = getenv("OSVERSION"))) {
+ value = atoi(temp);
+ return (value);
+ }
+
mib[0] = CTL_KERN;
mib[1] = KERN_OSRELDATE;
size = sizeof value;
if (sysctl(mib, 2, &value, &size, NULL, 0) == -1)
return (-1);
- if ((temp = getenv("OSVERSION")))
- value = atoi(temp);
return (value);
}
diff --git a/lib/libc/gen/getpagesize.c b/lib/libc/gen/getpagesize.c
index d796b9d..f4b8128 100644
--- a/lib/libc/gen/getpagesize.c
+++ b/lib/libc/gen/getpagesize.c
@@ -36,8 +36,12 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/sysctl.h>
+#include <errno.h>
+#include <link.h>
#include <unistd.h>
+#include "libc_private.h"
+
/*
* This is unlikely to change over the running time of any
* program, so we cache the result to save some syscalls.
@@ -52,13 +56,20 @@ getpagesize()
int mib[2];
static int value;
size_t size;
+ int error;
+
+ if (value != 0)
+ return (value);
+
+ error = _elf_aux_info(AT_PAGESZ, &value, sizeof(value));
+ if (error == 0 && value != 0)
+ return (value);
+
+ mib[0] = CTL_HW;
+ mib[1] = HW_PAGESIZE;
+ size = sizeof value;
+ if (sysctl(mib, 2, &value, &size, NULL, 0) == -1)
+ return (-1);
- if (!value) {
- mib[0] = CTL_HW;
- mib[1] = HW_PAGESIZE;
- size = sizeof value;
- if (sysctl(mib, 2, &value, &size, NULL, 0) == -1)
- return (-1);
- }
return (value);
}
diff --git a/lib/libc/gen/getpagesizes.c b/lib/libc/gen/getpagesizes.c
index b0de939..534fe9e 100644
--- a/lib/libc/gen/getpagesizes.c
+++ b/lib/libc/gen/getpagesizes.c
@@ -32,6 +32,9 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <errno.h>
+#include <link.h>
+
+#include "libc_private.h"
/*
* Retrieves page size information from the system. Specifically, returns the
@@ -51,7 +54,7 @@ getpagesizes(size_t pagesize[], int nelem)
static u_long ps[MAXPAGESIZES];
static int nops;
size_t size;
- int i;
+ int error, i;
if (nelem < 0 || (nelem > 0 && pagesize == NULL)) {
errno = EINVAL;
@@ -59,9 +62,13 @@ getpagesizes(size_t pagesize[], int nelem)
}
/* Cache the result of the sysctl(2). */
if (nops == 0) {
+ error = _elf_aux_info(AT_PAGESIZES, ps, sizeof(ps));
size = sizeof(ps);
- if (sysctlbyname("hw.pagesizes", ps, &size, NULL, 0) == -1)
- return (-1);
+ if (error != 0 || ps[0] == 0) {
+ if (sysctlbyname("hw.pagesizes", ps, &size, NULL, 0)
+ == -1)
+ return (-1);
+ }
/* Count the number of page sizes that are supported. */
nops = size / sizeof(ps[0]);
while (nops > 0 && ps[nops - 1] == 0)
diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h
index cb0b407..570441b 100644
--- a/lib/libc/include/libc_private.h
+++ b/lib/libc/include/libc_private.h
@@ -213,4 +213,6 @@ extern int __sys_fcntl(int, int, ...);
/* execve() with PATH processing to implement posix_spawnp() */
int _execvpe(const char *, char * const *, char * const *);
+int _elf_aux_info(int aux, void *buf, int buflen);
+
#endif /* _LIBC_PRIVATE_H_ */
diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c
index 1b581d4..f1a13ef 100644
--- a/lib/libc/stdlib/malloc.c
+++ b/lib/libc/stdlib/malloc.c
@@ -180,6 +180,7 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <limits.h>
+#include <link.h>
#include <pthread.h>
#include <sched.h>
#include <stdarg.h>
@@ -194,6 +195,8 @@ __FBSDID("$FreeBSD$");
#include "un-namespace.h"
+#include "libc_private.h"
+
#define RB_COMPACT
#include "rb.h"
#if (defined(MALLOC_TCACHE) && defined(MALLOC_STATS))
@@ -5353,14 +5356,20 @@ small_size2bin_init_hard(void)
static unsigned
malloc_ncpus(void)
{
+ int mib[2];
unsigned ret;
- size_t retlen = sizeof(ret);
- int mib[] = {CTL_HW, HW_NCPU};
-
- if (sysctl(mib, sizeof(mib) / sizeof(int), &ret, &retlen,
- (void *)0, 0) == -1) {
- /* Error. */
- ret = 1;
+ int error;
+ size_t len;
+
+ error = _elf_aux_info(AT_NCPUS, &ret, sizeof(ret));
+ if (error != 0 || ret == 0) {
+ mib[0] = CTL_HW;
+ mib[1] = HW_NCPU;
+ len = sizeof(ret);
+ if (sysctl(mib, 2, &ret, &len, (void *)NULL, 0) == -1) {
+ /* Error. */
+ ret = 1;
+ }
}
return (ret);
diff --git a/lib/libc/sys/stack_protector.c b/lib/libc/sys/stack_protector.c
index 14c20eb..b0108f9 100644
--- a/lib/libc/sys/stack_protector.c
+++ b/lib/libc/sys/stack_protector.c
@@ -34,10 +34,13 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/types.h>
+#include <errno.h>
+#include <link.h>
#include <signal.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
+#include "libc_private.h"
extern int __sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
void *newp, size_t newlen);
@@ -54,9 +57,14 @@ __guard_setup(void)
{
int mib[2];
size_t len;
+ int error;
if (__stack_chk_guard[0] != 0)
return;
+ error = _elf_aux_info(AT_CANARY, __stack_chk_guard,
+ sizeof(__stack_chk_guard));
+ if (error == 0 && __stack_chk_guard[0] != 0)
+ return;
mib[0] = CTL_KERN;
mib[1] = KERN_ARND;
OpenPOWER on IntegriCloud