From 67eb8c6c04a1b6c6fb85cf9cd6d7bdde489c4d5d Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Tue, 11 Sep 2018 22:16:41 -0500 Subject: cxx_thread: Add __cxa_thread_atexit_impl Signed-off-by: Samuel Holland --- CHANGELOG.rst | 5 +++++ Makefile | 1 + libgcompat/cxx_thread.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 libgcompat/cxx_thread.c diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ee9851d..2902cb3 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,6 +17,11 @@ Build system * Allow building against libucontext. +cxx_thread +---------- + +* Add __cxa_thread_atexit_impl. + math ---- diff --git a/Makefile b/Makefile index 06af84f..74c25f6 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ LIBGCOMPAT_INCLUDE = \ libgcompat/alias.h LIBGCOMPAT_SRC = \ + libgcompat/cxx_thread.c \ libgcompat/dlfcn.c \ libgcompat/error.c \ libgcompat/execinfo.c \ diff --git a/libgcompat/cxx_thread.c b/libgcompat/cxx_thread.c new file mode 100644 index 0000000..105e4c5 --- /dev/null +++ b/libgcompat/cxx_thread.c @@ -0,0 +1,56 @@ +#include /* NULL, pthread_{key,once,{get,set}specific} */ +#include /* malloc, free */ + +#include "internal.h" + +struct dtor_node { + struct dtor_node *next; + void (*func)(void *); + void *obj; +}; + +static pthread_key_t key; +static pthread_once_t once = PTHREAD_ONCE_INIT; + +static void run_dtors(void *head) +{ + struct dtor_node *next, *node = head; + + while (node != NULL) { + next = node->next; + node->func(node->obj); + free(node); + node = next; + } +} + +static void create_key(void) +{ + int res = pthread_key_create(&key, run_dtors); + + GCOMPAT__assert_with_reason(res, "No key for thread_atexit list"); +} + +/** + * Register a destructor to run at thread exit. + * + * See + * https://sourceware.org/glibc/wiki/Destructor%20support%20for%20thread_local%20variables + */ +int __cxa_thread_atexit_impl(void (*func)(void *), void *obj, void *dso_symbol) +{ + struct dtor_node *node; + + pthread_once(&once, create_key); + + node = malloc(sizeof(*node)); + GCOMPAT__assert_with_reason(node, "No memory for thread_atexit node"); + node->next = pthread_getspecific(key); + node->func = func; + node->obj = obj; + + int res = pthread_setspecific(key, node); + GCOMPAT__assert_with_reason(!res, "Cannot update thread_atexit list"); + + return 0; +} -- cgit v1.2.3-70-g09d2 From fc611beda52e6063bf0510a84313d70eb033a672 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Tue, 11 Sep 2018 22:19:45 -0500 Subject: ctype: Add __ctype_b Signed-off-by: Samuel Holland --- CHANGELOG.rst | 6 ++++++ Makefile | 1 + libgcompat/ctype.c | 1 + 3 files changed, 8 insertions(+) create mode 100644 libgcompat/ctype.c diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2902cb3..f86ecdc 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,6 +17,12 @@ Build system * Allow building against libucontext. +ctype +----- + +* Add __ctype_b. + + cxx_thread ---------- diff --git a/Makefile b/Makefile index 74c25f6..272bfd9 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ LIBGCOMPAT_INCLUDE = \ libgcompat/alias.h LIBGCOMPAT_SRC = \ + libgcompat/ctype.c \ libgcompat/cxx_thread.c \ libgcompat/dlfcn.c \ libgcompat/error.c \ diff --git a/libgcompat/ctype.c b/libgcompat/ctype.c new file mode 100644 index 0000000..1ae9877 --- /dev/null +++ b/libgcompat/ctype.c @@ -0,0 +1 @@ +const unsigned short int *__ctype_b; -- cgit v1.2.3-70-g09d2 From 71d20ba411d3923934409936ba20f6ead8a6cbcd Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Tue, 11 Sep 2018 22:20:17 -0500 Subject: readlink: Report ENOSYS on dlsym failure Signed-off-by: Samuel Holland --- CHANGELOG.rst | 6 ++++++ libgcompat/readlink.c | 2 ++ 2 files changed, 8 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f86ecdc..2a4b1d3 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -35,6 +35,12 @@ math * Add most __*_finite functions, courtesy of Elizabeth Myers. +readlink +-------- + +* Report ENOSYS on dlsym failure. + + resolv ------ diff --git a/libgcompat/readlink.c b/libgcompat/readlink.c index 63def96..0db094c 100644 --- a/libgcompat/readlink.c +++ b/libgcompat/readlink.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -18,6 +19,7 @@ ssize_t readlink(const char *path, char *buf, size_t len) if (real_readlink == NULL) { real_readlink = dlsym(RTLD_NEXT, "readlink"); if (real_readlink == NULL) { + errno = ENOSYS; return -1; } } -- cgit v1.2.3-70-g09d2 From e9224395eba97e86d8d411f016972b2d70cd6ff3 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Tue, 11 Sep 2018 22:28:24 -0500 Subject: realpath: Intercept realpath(/proc/self/exe) Reuse the machinery from readlink Signed-off-by: Samuel Holland --- CHANGELOG.rst | 5 +++-- Makefile | 1 + libgcompat/realpath.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 libgcompat/realpath.c diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2a4b1d3..188d75c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -35,9 +35,10 @@ math * Add most __*_finite functions, courtesy of Elizabeth Myers. -readlink --------- +readlink/realpath +----------------- +* Intercept realpath as well as readlink. * Report ENOSYS on dlsym failure. diff --git a/Makefile b/Makefile index 272bfd9..934422f 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,7 @@ LIBGCOMPAT_SRC = \ libgcompat/pthread.c \ libgcompat/pwd.c \ libgcompat/readlink.c \ + libgcompat/realpath.c \ libgcompat/resolv.c \ libgcompat/resource.c \ libgcompat/setjmp.c \ diff --git a/libgcompat/realpath.c b/libgcompat/realpath.c new file mode 100644 index 0000000..ab68cc4 --- /dev/null +++ b/libgcompat/realpath.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef LINKER +#error LINKER must be defined +#endif + +static char *(*real_realpath)(const char *restrict, char *restrict); + +char *realpath(const char *restrict path, char *restrict resolved) +{ + if (real_realpath == NULL) { + real_realpath = dlsym(RTLD_NEXT, "realpath"); + if (real_realpath == NULL) { + errno = ENOSYS; + return NULL; + } + } + + if (!strcmp(path, "/proc/self/exe")) { + char *fixed = resolved; + + if (fixed == NULL) { + fixed = malloc(PATH_MAX); + if (fixed == NULL) { + errno = ENOMEM; + return NULL; + } + } + + /* If passed in, the buffer is at least PATH_MAX per POSIX. */ + ssize_t written = readlink(path, fixed, PATH_MAX - 1); + if (written == -1) { + /* Free the buffer iff we allocated it. */ + if (fixed != resolved) + free(fixed); + return NULL; + } + fixed[written] = '\0'; + + return fixed; + } + + return real_realpath(path, resolved); +} -- cgit v1.2.3-70-g09d2 From 5c4d07699c7c6f83d10657f03ae89dee6735226f Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Tue, 11 Sep 2018 22:30:45 -0500 Subject: readlink: Report EIO on /proc read failure Signed-off-by: Samuel Holland --- CHANGELOG.rst | 1 + libgcompat/readlink.c | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 188d75c..96de004 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -39,6 +39,7 @@ readlink/realpath ----------------- * Intercept realpath as well as readlink. +* Report EIO on /proc read failure. * Report ENOSYS on dlsym failure. diff --git a/libgcompat/readlink.c b/libgcompat/readlink.c index 0db094c..9b3e2dd 100644 --- a/libgcompat/readlink.c +++ b/libgcompat/readlink.c @@ -80,6 +80,7 @@ ssize_t readlink(const char *path, char *buf, size_t len) close(fd); fail: exe[0] = '\0'; + errno = EIO; return -1; } -- cgit v1.2.3-70-g09d2 From c7fc46aeb0ea9637deb242fbdba2e07cb63a44f6 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Tue, 11 Sep 2018 22:43:54 -0500 Subject: stdlib: Add secure_getenv alias to __secure_getenv Signed-off-by: Samuel Holland --- CHANGELOG.rst | 6 ++++++ libgcompat/stdlib.c | 3 +++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 96de004..f97724f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -55,6 +55,12 @@ socket * Add __poll_chk +stdlib +------ + +* Add secure_getenv alias to __secure_getenv. + + string ------ diff --git a/libgcompat/stdlib.c b/libgcompat/stdlib.c index a08f914..82f7602 100644 --- a/libgcompat/stdlib.c +++ b/libgcompat/stdlib.c @@ -5,6 +5,8 @@ #include /* getenv, realpath, strto* */ #include /* get*id */ +#include "alias.h" + /** * Resolve a pathname, with buffer overflow checking. * @@ -30,6 +32,7 @@ char *__secure_getenv(const char *name) return getenv(name); } +weak_alias(__secure_getenv, secure_getenv); /** * Underlying function for strtod. -- cgit v1.2.3-70-g09d2 From d8e667a638401df1bf881b16fcda6315f3fa3eb1 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Tue, 11 Sep 2018 22:45:16 -0500 Subject: unistd: Add __open_2 and its __open64_2 alias Signed-off-by: Samuel Holland --- CHANGELOG.rst | 5 +++++ libgcompat/unistd.c | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f97724f..edc96f5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -68,6 +68,11 @@ string * Add memfrob. * Add strfry. +unistd +------ + +* Add __open_2/__open64_2. + malloc ------ diff --git a/libgcompat/unistd.c b/libgcompat/unistd.c index e19ec8e..d2f3097 100644 --- a/libgcompat/unistd.c +++ b/libgcompat/unistd.c @@ -1,4 +1,5 @@ #include /* assert */ +#include /* O_CREAT */ #include /* NGROUPS_MAX */ #include /* NULL, size_t */ #include /* confstr, getcwd, getgroups, ... */ @@ -90,6 +91,14 @@ pid_t __getpgid(pid_t pid) return getpgid(pid); } +int __open_2(const char *path, int oflag) +{ + assert(!(oflag & O_CREAT)); + + return open(path, oflag); +} +alias(__open_2, __open64_2); + /** * Read from a file, with buffer overflow checking. * -- cgit v1.2.3-70-g09d2 From 9bc7c737b311fcbba71af11884b7f9111dba57ba Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Tue, 11 Sep 2018 22:41:30 -0500 Subject: libgcompat: Fix formatting inconsistencies (clang-format) Signed-off-by: Samuel Holland --- libgcompat/gnulib.c | 16 +++++++++------- libgcompat/internal.c | 3 +-- libgcompat/math.c | 13 +++++-------- libgcompat/resolv.c | 2 +- libgcompat/socket.c | 2 +- libgcompat/string.c | 9 ++++----- 6 files changed, 21 insertions(+), 24 deletions(-) diff --git a/libgcompat/gnulib.c b/libgcompat/gnulib.c index ccdec24..3f66963 100644 --- a/libgcompat/gnulib.c +++ b/libgcompat/gnulib.c @@ -1,16 +1,18 @@ #include #include "internal.h" -#define REASON_FD_SET_OVERFLOW \ - "Fault: Overflow in fd_set detected.\n" \ - "Description: This is caused by a programmer naively attempting to redefine FD_SETSIZE,\n" \ - " which is not allowed on POSIX platforms. The program must be either rebuilt\n" \ - " with the correct FD_SETSIZE definition, or preferably rewritten to avoid use\n" \ - " of select(2) in general. See also: poll(2).\n" \ +#define REASON_FD_SET_OVERFLOW \ + "Fault: Overflow in fd_set detected.\n" \ + "Description: This is caused by a programmer naively attempting to\n" \ + " redefine FD_SETSIZE, which is not allowed on POSIX platforms.\n" \ + " The program must either be rebuilt with the correct FD_SETSIZE\n" \ + " definition, or else be rewritten to avoid use of select(2) in \n" \ + " general. See also: poll(2).\n" \ " libgcompat believes FD_SETSIZE to be %zu.\n" unsigned long __fdelt_chk(unsigned long size) { - GCOMPAT__assert_with_reason(size < FD_SETSIZE, REASON_FD_SET_OVERFLOW, FD_SETSIZE); + GCOMPAT__assert_with_reason(size < FD_SETSIZE, REASON_FD_SET_OVERFLOW, + FD_SETSIZE); return size / (sizeof(unsigned long) << 3); } diff --git a/libgcompat/internal.c b/libgcompat/internal.c index 441b3cc..450c5e4 100644 --- a/libgcompat/internal.c +++ b/libgcompat/internal.c @@ -1,8 +1,7 @@ -#include #include +#include #include - void GCOMPAT__panic(const char *fmt, ...) { va_list va; diff --git a/libgcompat/math.c b/libgcompat/math.c index 83abbf4..793ff1a 100644 --- a/libgcompat/math.c +++ b/libgcompat/math.c @@ -1,8 +1,8 @@ -#define _GNU_SOURCE /* Extra maths functions */ -#include /* Literally everything */ +#define _GNU_SOURCE /* Extra maths functions */ +#include /* Literally everything */ -#include "alias.h" /* weak_alias */ -#include "internal.h" /* GCOMPAT__assert_with_reason */ +#include "alias.h" /* weak_alias */ +#include "internal.h" /* GCOMPAT__assert_with_reason */ /** * Multiplies the first argument x by FLT_RADIX (probably 2) to the power of y. @@ -14,7 +14,7 @@ long double scalbl(long double x, long double y) * 1) Good Enough(TM) * 2) scalbl is deprecated anyway * */ - return scalblnl(x, (long int)y); + return scalblnl(x, (long int) y); } /* @@ -144,7 +144,6 @@ int __isnan(double arg) } weak_alias(__isnan, isnan); - /** * Test for a NaN. * @@ -290,7 +289,6 @@ long double __asinl_finite(long double x) return res; } - /** * Returns the principal value of the arc tangent of x/y, expressed in radians. */ @@ -363,7 +361,6 @@ long double __atanhl_finite(long double x) return res; } - /** * Returns the hyperbolic cosine of x. */ diff --git a/libgcompat/resolv.c b/libgcompat/resolv.c index f70d913..0b81d0c 100644 --- a/libgcompat/resolv.c +++ b/libgcompat/resolv.c @@ -42,7 +42,7 @@ int __res_nclose(res_state statp) weak_alias(__res_nclose, res_nclose); int __res_search(const char *dname, int class, int type, unsigned char *answer, - int anslen) + int anslen) { return res_search(dname, class, type, answer, anslen); } diff --git a/libgcompat/socket.c b/libgcompat/socket.c index 9919ee0..e56199e 100644 --- a/libgcompat/socket.c +++ b/libgcompat/socket.c @@ -1,6 +1,6 @@ #include /* assert */ +#include /* poll, pollfd, nfds_t */ #include /* NULL */ -#include /* poll, pollfd, nfds_t */ #include /* recv, recvfrom */ /** diff --git a/libgcompat/string.c b/libgcompat/string.c index 9f1704b..f4e0620 100644 --- a/libgcompat/string.c +++ b/libgcompat/string.c @@ -2,10 +2,10 @@ #include /* assert */ #include /* NULL, size_t */ #include /* SIZE_MAX */ -#include /* memcpy, strcpy, strncat, strndup */ #include /* rand_r */ -#include /* getpid */ +#include /* memcpy, strcpy, strncat, strndup */ #include /* time */ +#include /* getpid */ #include "alias.h" /* weak_alias */ @@ -189,8 +189,7 @@ size_t __strcspn_c2(const char *str, int bad, int bad2) { size_t length = 0; const char *s = str; - while(*s != bad && *s != bad2 && *s != '\0') - { + while (*s != bad && *s != bad2 && *s != '\0') { length++; s++; } @@ -285,7 +284,7 @@ char *strfry(char *s) if (!len) return s; - seed += time(NULL) ^ getpid() ^ (uintptr_t)s; + seed += time(NULL) ^ getpid() ^ (uintptr_t) s; for (i = 0; i < len - 1; ++i) { j = rand_r(&seed) % (len - i) + i; -- cgit v1.2.3-70-g09d2