diff options
Diffstat (limited to 'libc/bionic')
-rw-r--r-- | libc/bionic/__poll_chk.cpp | 49 | ||||
-rw-r--r-- | libc/bionic/fchmod.cpp | 72 | ||||
-rw-r--r-- | libc/bionic/fchmodat.cpp | 67 | ||||
-rw-r--r-- | libc/bionic/jemalloc.h | 1 | ||||
-rw-r--r-- | libc/bionic/libc_logging.cpp | 24 | ||||
-rw-r--r-- | libc/bionic/poll.cpp | 1 |
6 files changed, 201 insertions, 13 deletions
diff --git a/libc/bionic/__poll_chk.cpp b/libc/bionic/__poll_chk.cpp new file mode 100644 index 000000000..3acac4e6a --- /dev/null +++ b/libc/bionic/__poll_chk.cpp @@ -0,0 +1,49 @@ +/* + * 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 <poll.h> +#include "private/libc_logging.h" + +#include <stdio.h> + +extern "C" int __poll_chk(struct pollfd* fds, nfds_t fd_count, int timeout, size_t fds_size) { +fprintf(stderr, "__poll_chk %p %i %i %i\n", fds, (int)fd_count, timeout, (int) fds_size); + if (__predict_false(fds_size / sizeof(*fds) < fd_count)) { + __fortify_chk_fail("poll: pollfd array smaller than fd count", 0); + } + return poll(fds, fd_count, timeout); +} + +extern "C" int __ppoll_chk(struct pollfd* fds, nfds_t fd_count, const struct timespec* timeout, const sigset_t* mask, size_t fds_size) { +fprintf(stderr, "__ppoll_chk %p %i %p %p %i\n", fds, (int)fd_count, timeout, mask, (int) fds_size); + if (__predict_false(fds_size / sizeof(*fds) < fd_count)) { + __fortify_chk_fail("ppoll: pollfd array smaller than fd count", 0); + } + return ppoll(fds, fd_count, timeout, mask); +} diff --git a/libc/bionic/fchmod.cpp b/libc/bionic/fchmod.cpp new file mode 100644 index 000000000..6e020b6be --- /dev/null +++ b/libc/bionic/fchmod.cpp @@ -0,0 +1,72 @@ +/* + * 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. + */ + +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <errno.h> +#include <unistd.h> +#include <stdio.h> + +extern "C" int __fchmod(int, mode_t); + +int fchmod(int fd, mode_t mode) { + int saved_errno = errno; + int result = __fchmod(fd, mode); + + if ((result == 0) || (errno != EBADF)) { + return result; + } + + // fd could be an O_PATH file descriptor, and the kernel + // may not directly support fchmod() on such a file descriptor. + // Use /proc/self/fd instead to emulate this support. + // https://sourceware.org/bugzilla/show_bug.cgi?id=14578 + // + // As of February 2015, there are no kernels which support fchmod + // on an O_PATH file descriptor, and "man open" documents fchmod + // on O_PATH file descriptors as returning EBADF. + int fd_flag = fcntl(fd, F_GETFL); + if ((fd_flag == -1) || ((fd_flag & O_PATH) == 0)) { + errno = EBADF; + return -1; + } + + char buf[40]; + snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd); + errno = saved_errno; + result = chmod(buf, mode); + if ((result == -1) && (errno == ELOOP)) { + // Linux does not support changing the mode of a symlink. + // For fchmodat(AT_SYMLINK_NOFOLLOW), POSIX requires a return + // value of ENOTSUP. Assume that's true here too. + errno = ENOTSUP; + } + + return result; +} diff --git a/libc/bionic/fchmodat.cpp b/libc/bionic/fchmodat.cpp new file mode 100644 index 000000000..c28e15ac7 --- /dev/null +++ b/libc/bionic/fchmodat.cpp @@ -0,0 +1,67 @@ +/* + * 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. + */ + +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <errno.h> +#include <unistd.h> + +#include "private/ErrnoRestorer.h" + +extern "C" int __fchmodat(int, const char*, mode_t); + +int fchmodat(int dirfd, const char* pathname, mode_t mode, int flags) { + if ((flags & ~AT_SYMLINK_NOFOLLOW) != 0) { + errno = EINVAL; + return -1; + } + + if (flags & AT_SYMLINK_NOFOLLOW) { + // Emulate AT_SYMLINK_NOFOLLOW using the mechanism described + // at https://sourceware.org/bugzilla/show_bug.cgi?id=14578 + // comment #10 + + int fd = openat(dirfd, pathname, O_PATH | O_NOFOLLOW | O_CLOEXEC); + if (fd == -1) { + return -1; // returns errno from openat + } + + // POSIX requires that ENOTSUP be returned when the system + // doesn't support setting the mode of a symbolic link. + // This is true for all Linux kernels. + // We rely on the O_PATH compatibility layer added in the + // fchmod() function to get errno correct. + int result = fchmod(fd, mode); + ErrnoRestorer errno_restorer; // don't let close() clobber errno + close(fd); + return result; + } + + return __fchmodat(dirfd, pathname, mode); +} diff --git a/libc/bionic/jemalloc.h b/libc/bionic/jemalloc.h index feb1f43a5..98ea0eedb 100644 --- a/libc/bionic/jemalloc.h +++ b/libc/bionic/jemalloc.h @@ -18,6 +18,7 @@ #define LIBC_BIONIC_JEMALLOC_H_ #include <jemalloc/jemalloc.h> +#include <malloc.h> // For struct mallinfo. // Need to wrap memalign since je_memalign fails on non-power of 2 alignments. #define je_memalign je_memalign_round_up_boundary diff --git a/libc/bionic/libc_logging.cpp b/libc/bionic/libc_logging.cpp index 49a37628f..76bc46ddf 100644 --- a/libc/bionic/libc_logging.cpp +++ b/libc/bionic/libc_logging.cpp @@ -438,7 +438,7 @@ static int __libc_write_stderr(const char* tag, const char* msg) { vec[1].iov_base = const_cast<char*>(": "); vec[1].iov_len = 2; vec[2].iov_base = const_cast<char*>(msg); - vec[2].iov_len = strlen(msg) + 1; + vec[2].iov_len = strlen(msg); vec[3].iov_base = const_cast<char*>("\n"); vec[3].iov_len = 1; @@ -448,8 +448,7 @@ static int __libc_write_stderr(const char* tag, const char* msg) { } #ifdef TARGET_USES_LOGD -static int __libc_open_log_socket() -{ +static int __libc_open_log_socket() { // ToDo: Ideally we want this to fail if the gid of the current // process is AID_LOGD, but will have to wait until we have // registered this in private/android_filesystem_config.h. We have @@ -491,7 +490,6 @@ struct log_time { // Wire format static int __libc_write_log(int priority, const char* tag, const char* msg) { #ifdef TARGET_USES_LOGD int main_log_fd = __libc_open_log_socket(); - if (main_log_fd == -1) { // Try stderr instead. return __libc_write_stderr(tag, msg); @@ -515,9 +513,9 @@ static int __libc_write_log(int priority, const char* tag, const char* msg) { vec[3].iov_base = &priority; vec[3].iov_len = 1; vec[4].iov_base = const_cast<char*>(tag); - vec[4].iov_len = strlen(tag) + 1; + vec[4].iov_len = strlen(tag); vec[5].iov_base = const_cast<char*>(msg); - vec[5].iov_len = strlen(msg) + 1; + vec[5].iov_len = strlen(msg); #else int main_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/main", O_CLOEXEC | O_WRONLY)); if (main_log_fd == -1) { @@ -532,9 +530,9 @@ static int __libc_write_log(int priority, const char* tag, const char* msg) { vec[0].iov_base = &priority; vec[0].iov_len = 1; vec[1].iov_base = const_cast<char*>(tag); - vec[1].iov_len = strlen(tag) + 1; + vec[1].iov_len = strlen(tag); vec[2].iov_base = const_cast<char*>(msg); - vec[2].iov_len = strlen(msg) + 1; + vec[2].iov_len = strlen(msg); #endif int result = TEMP_FAILURE_RETRY(writev(main_log_fd, vec, sizeof(vec) / sizeof(vec[0]))); @@ -614,7 +612,7 @@ void __fortify_chk_fail(const char* msg, uint32_t tag) { if (tag != 0) { __libc_android_log_event_uid(tag); } - __libc_fatal("FORTIFY_SOURCE: %s. Calling abort().", msg); + __libc_fatal("FORTIFY: %s", msg); } static void __libc_fatal(const char* format, va_list args) { @@ -622,12 +620,12 @@ static void __libc_fatal(const char* format, va_list args) { BufferOutputStream os(msg, sizeof(msg)); out_vformat(os, format, args); - // log to stderr for the benefit of "adb shell" users. + // Log to stderr for the benefit of "adb shell" users. struct iovec iov[2] = { - {msg, strlen(msg)}, - {const_cast<void*>(static_cast<const void*>("\n")), 1}, + { msg, os.total }, + { const_cast<char*>("\n"), 1 }, }; - writev(2, iov, 2); + TEMP_FAILURE_RETRY(writev(2, iov, 2)); // Log to the log for the benefit of regular app developers (whose stdout and stderr are closed). __libc_write_log(ANDROID_LOG_FATAL, "libc", msg); diff --git a/libc/bionic/poll.cpp b/libc/bionic/poll.cpp index d267229b7..23ef90a8f 100644 --- a/libc/bionic/poll.cpp +++ b/libc/bionic/poll.cpp @@ -26,6 +26,7 @@ * SUCH DAMAGE. */ +#undef _FORTIFY_SOURCE #include <errno.h> #include <sys/poll.h> #include <sys/select.h> |