libc: add clang FORTIFY support
This patch adds clang-style FORTIFY to Bionic. For more information on
FORTIFY, please see https://goo.gl/8HS2dW . This implementation works
for versions of clang that don't support diagnose_if, so please see the
"without diagnose_if" sections. We plan to swap to a diagnose_if-based
FORTIFY later this year (since it doesn't really add any features; it
just simplifies the implementation a lot, and it gives us much prettier
diagnostics)
Bug: 32073964
Test: Builds on angler, bullhead, marlin, sailfish. Bionic CTS tests
pass on Angler and Bullhead.
Change-Id: I607aecbeee81529709b1eee7bef5b0836151eb2b
diff --git a/libc/include/poll.h b/libc/include/poll.h
index c4e62f9..3287a0c 100644
--- a/libc/include/poll.h
+++ b/libc/include/poll.h
@@ -38,27 +38,65 @@
typedef unsigned int nfds_t;
-int poll(struct pollfd*, nfds_t, int);
-int ppoll(struct pollfd*, nfds_t, const struct timespec*, const sigset_t*) __INTRODUCED_IN(21);
+int poll(struct pollfd*, nfds_t, int) __overloadable __RENAME_CLANG(poll);
+int ppoll(struct pollfd*, nfds_t, const struct timespec*, const sigset_t*)
+ __overloadable __RENAME_CLANG(ppoll) __INTRODUCED_IN(21);
int __poll_chk(struct pollfd*, nfds_t, int, size_t) __INTRODUCED_IN(23);
+int __ppoll_chk(struct pollfd*, nfds_t, const struct timespec*, const sigset_t*, size_t)
+ __INTRODUCED_IN(23);
+
+#if defined(__BIONIC_FORTIFY)
+#if __ANDROID_API__ >= __ANDROID_API_M__
+#if defined(__clang__)
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+int poll(struct pollfd* fds, nfds_t fd_count, int timeout) __overloadable
+ __enable_if(__bos(fds) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
+ __bos(fds) < sizeof(*fds) * fd_count,
+ "selected when there aren't fd_count fds")
+ __errorattr("too many fds specified");
+
+__BIONIC_FORTIFY_INLINE
+int poll(struct pollfd* const fds __pass_object_size, nfds_t fd_count,
+ int timeout) __overloadable {
+ size_t bos_fds = __bos(fds);
+
+ if (bos_fds == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+ return __call_bypassing_fortify(poll)(fds, fd_count, timeout);
+ }
+
+ return __poll_chk(fds, fd_count, timeout, bos_fds);
+}
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+int ppoll(struct pollfd* fds, nfds_t fd_count, const struct timespec* timeout,
+ const sigset_t* mask) __overloadable
+ __enable_if(__bos(fds) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
+ __bos(fds) < sizeof(*fds) * fd_count,
+ "selected when there aren't fd_count fds")
+ __errorattr("too many fds specified");
+
+__BIONIC_FORTIFY_INLINE
+int ppoll(struct pollfd* const fds __pass_object_size, nfds_t fd_count,
+ const struct timespec* timeout, const sigset_t* mask) __overloadable {
+ size_t bos_fds = __bos(fds);
+
+ if (bos_fds == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+ return __call_bypassing_fortify(ppoll)(fds, fd_count, timeout, mask);
+ }
+
+ return __ppoll_chk(fds, fd_count, timeout, mask, bos_fds);
+}
+#else /* defined(__clang__) */
int __poll_real(struct pollfd*, nfds_t, int) __RENAME(poll);
__errordecl(__poll_too_small_error, "poll: pollfd array smaller than fd count");
-int __ppoll_chk(struct pollfd*, nfds_t, const struct timespec*, const sigset_t*, size_t)
- __INTRODUCED_IN(23);
int __ppoll_real(struct pollfd*, nfds_t, const struct timespec*, const sigset_t*) __RENAME(ppoll)
__INTRODUCED_IN(21);
__errordecl(__ppoll_too_small_error, "ppoll: pollfd array smaller than fd count");
-#if defined(__BIONIC_FORTIFY)
-
-#if __ANDROID_API__ >= __ANDROID_API_M__
__BIONIC_FORTIFY_INLINE
int poll(struct pollfd* fds, nfds_t fd_count, int timeout) {
-#if defined(__clang__)
- return __poll_chk(fds, fd_count, timeout, __bos(fds));
-#else
if (__bos(fds) != __BIONIC_FORTIFY_UNKNOWN_SIZE) {
if (!__builtin_constant_p(fd_count)) {
return __poll_chk(fds, fd_count, timeout, __bos(fds));
@@ -67,14 +105,11 @@
}
}
return __poll_real(fds, fd_count, timeout);
-#endif
}
__BIONIC_FORTIFY_INLINE
-int ppoll(struct pollfd* fds, nfds_t fd_count, const struct timespec* timeout, const sigset_t* mask) {
-#if defined(__clang__)
- return __ppoll_chk(fds, fd_count, timeout, mask, __bos(fds));
-#else
+int ppoll(struct pollfd* fds, nfds_t fd_count, const struct timespec* timeout,
+ const sigset_t* mask) {
if (__bos(fds) != __BIONIC_FORTIFY_UNKNOWN_SIZE) {
if (!__builtin_constant_p(fd_count)) {
return __ppoll_chk(fds, fd_count, timeout, mask, __bos(fds));
@@ -83,11 +118,11 @@
}
}
return __ppoll_real(fds, fd_count, timeout, mask);
-#endif
}
-#endif /* __ANDROID_API__ >= __ANDROID_API_M__ */
-#endif
+#endif /* defined(__clang__) */
+#endif /* __ANDROID_API__ >= __ANDROID_API_M__ */
+#endif /* defined(__BIONIC_FORTIFY) */
__END_DECLS