diff options
Diffstat (limited to 'libc/bionic')
-rw-r--r-- | libc/bionic/__pread64_chk.cpp | 43 | ||||
-rw-r--r-- | libc/bionic/__pread_chk.cpp | 43 | ||||
-rw-r--r-- | libc/bionic/legacy_32_bit_support.cpp | 2 | ||||
-rw-r--r-- | libc/bionic/posix_timers.cpp | 42 |
4 files changed, 108 insertions, 22 deletions
diff --git a/libc/bionic/__pread64_chk.cpp b/libc/bionic/__pread64_chk.cpp new file mode 100644 index 0000000..5d6ad2d --- /dev/null +++ b/libc/bionic/__pread64_chk.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + */ + +#undef _FORTIFY_SOURCE +#include <unistd.h> +#include "private/libc_logging.h" + +extern "C" ssize_t __pread64_chk(int fd, void* buf, size_t count, off64_t offset, size_t buf_size) { + if (__predict_false(count > buf_size)) { + __fortify_chk_fail("pread64: prevented write past end of buffer", 0); + } + + if (__predict_false(count > SSIZE_MAX)) { + __fortify_chk_fail("pread64: count > SSIZE_MAX", 0); + } + + return pread64(fd, buf, count, offset); +} diff --git a/libc/bionic/__pread_chk.cpp b/libc/bionic/__pread_chk.cpp new file mode 100644 index 0000000..7109ce6 --- /dev/null +++ b/libc/bionic/__pread_chk.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + */ + +#undef _FORTIFY_SOURCE +#include <unistd.h> +#include "private/libc_logging.h" + +extern "C" ssize_t __pread_chk(int fd, void* buf, size_t count, off_t offset, size_t buf_size) { + if (__predict_false(count > buf_size)) { + __fortify_chk_fail("pread: prevented write past end of buffer", 0); + } + + if (__predict_false(count > SSIZE_MAX)) { + __fortify_chk_fail("pread: count > SSIZE_MAX", 0); + } + + return pread(fd, buf, count, offset); +} diff --git a/libc/bionic/legacy_32_bit_support.cpp b/libc/bionic/legacy_32_bit_support.cpp index 50e4643..a107664 100644 --- a/libc/bionic/legacy_32_bit_support.cpp +++ b/libc/bionic/legacy_32_bit_support.cpp @@ -26,6 +26,8 @@ * SUCH DAMAGE. */ +#undef _FORTIFY_SOURCE + #include <errno.h> #include <fcntl.h> #include <stdarg.h> diff --git a/libc/bionic/posix_timers.cpp b/libc/bionic/posix_timers.cpp index 9991573..bc3aeb2 100644 --- a/libc/bionic/posix_timers.cpp +++ b/libc/bionic/posix_timers.cpp @@ -26,14 +26,15 @@ * SUCH DAMAGE. */ -#include "pthread_internal.h" -#include "private/bionic_futex.h" #include "private/kernel_sigset_t.h" #include <errno.h> #include <malloc.h> +#include <pthread.h> +#include <stdatomic.h> #include <stdio.h> #include <string.h> +#include <time.h> // System calls. extern "C" int __rt_sigtimedwait(const sigset_t*, siginfo_t*, const struct timespec*, size_t); @@ -59,11 +60,11 @@ struct PosixTimer { int sigev_notify; - // These fields are only needed for a SIGEV_THREAD timer. + // The fields below are only needed for a SIGEV_THREAD timer. pthread_t callback_thread; void (*callback)(sigval_t); sigval_t callback_argument; - volatile bool armed; + atomic_bool deleted; // Set when the timer is deleted, to prevent further calling of callback. }; static __kernel_timer_t to_kernel_timer_id(timer_t timer) { @@ -85,8 +86,13 @@ static void* __timer_thread_start(void* arg) { continue; } - if (si.si_code == SI_TIMER && timer->armed) { + if (si.si_code == SI_TIMER) { // This signal was sent because a timer fired, so call the callback. + + // All events to the callback will be ignored when the timer is deleted. + if (atomic_load(&timer->deleted) == true) { + continue; + } timer->callback(timer->callback_argument); } else if (si.si_code == SI_TKILL) { // This signal was sent because someone wants us to exit. @@ -97,9 +103,7 @@ static void* __timer_thread_start(void* arg) { } static void __timer_thread_stop(PosixTimer* timer) { - // Immediately mark the timer as disarmed so even if some events - // continue to happen, the callback won't be called. - timer->armed = false; + atomic_store(&timer->deleted, true); pthread_kill(timer->callback_thread, TIMER_SIGNAL); } @@ -126,7 +130,7 @@ int timer_create(clockid_t clock_id, sigevent* evp, timer_t* timer_id) { // Otherwise, this must be SIGEV_THREAD timer... timer->callback = evp->sigev_notify_function; timer->callback_argument = evp->sigev_value; - timer->armed = false; + atomic_init(&timer->deleted, false); // Check arguments that the kernel doesn't care about but we do. if (timer->callback == NULL) { @@ -199,25 +203,19 @@ int timer_delete(timer_t id) { return 0; } -// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_getoverrun.html +// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_gettime.html int timer_gettime(timer_t id, itimerspec* ts) { return __timer_gettime(to_kernel_timer_id(id), ts); } -// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_getoverrun.html +// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_settime.html +// When using timer_settime to disarm a repeatable SIGEV_THREAD timer with a very small +// period (like below 1ms), the kernel may continue to send events to the callback thread +// for a few extra times. This behavior is fine because in POSIX standard: The effect of +// disarming or resetting a timer with pending expiration notifications is unspecified. int timer_settime(timer_t id, int flags, const itimerspec* ts, itimerspec* ots) { PosixTimer* timer= reinterpret_cast<PosixTimer*>(id); - int rc = __timer_settime(timer->kernel_timer_id, flags, ts, ots); - if (rc == 0) { - // Mark the timer as either being armed or disarmed. This avoids the - // callback being called after the disarm for SIGEV_THREAD timers only. - if (ts->it_value.tv_sec != 0 || ts->it_value.tv_nsec != 0) { - timer->armed = true; - } else { - timer->armed = false; - } - } - return rc; + return __timer_settime(timer->kernel_timer_id, flags, ts, ots); } // http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_getoverrun.html |