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/sys/socket.h b/libc/include/sys/socket.h
index f9f6764..997191e 100644
--- a/libc/include/sys/socket.h
+++ b/libc/include/sys/socket.h
@@ -317,25 +317,59 @@
 __socketcall int socket(int, int, int);
 __socketcall int socketpair(int, int, int, int*);
 
-ssize_t recv(int, void*, size_t, int);
+ssize_t recv(int, void*, size_t, int) __overloadable __RENAME_CLANG(recv);
 ssize_t send(int, const void*, size_t, int);
 
 __socketcall ssize_t sendto(int, const void*, size_t, int, const struct sockaddr*, socklen_t);
-__socketcall ssize_t recvfrom(int, void*, size_t, int, struct sockaddr*, socklen_t*);
+__socketcall ssize_t recvfrom(int, void*, size_t, int, struct sockaddr*,
+        socklen_t*) __overloadable __RENAME_CLANG(recvfrom);
 
-__errordecl(__recvfrom_error, "recvfrom called with size bigger than buffer");
-ssize_t __recvfrom_chk(int, void*, size_t, size_t, int, struct sockaddr*, socklen_t*)
-  __INTRODUCED_IN(21);
-ssize_t __recvfrom_real(int, void*, size_t, int, struct sockaddr*, socklen_t*) __RENAME(recvfrom);
+ssize_t __recvfrom_chk(int, void*, size_t, size_t, int, struct sockaddr*,
+        socklen_t*) __INTRODUCED_IN(21);
 
 #if defined(__BIONIC_FORTIFY)
 
+#if defined(__clang__)
 #if __ANDROID_API__ >= __ANDROID_API_N__
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+ssize_t recvfrom(int fd, void* const buf __pass_object_size, size_t len,
+                 int flags, struct sockaddr* src_addr, socklen_t* addr_len)
+        __overloadable
+        __enable_if(__bos(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
+                    __bos(buf) < len, "selected when the buffer is too small")
+        __errorattr("size is larger than the destination buffer");
+
 __BIONIC_FORTIFY_INLINE
-ssize_t recvfrom(int fd, void* buf, size_t len, int flags, struct sockaddr* src_addr, socklen_t* addr_len) {
+ssize_t recvfrom(int fd, void* const buf __pass_object_size, size_t len,
+                 int flags, struct sockaddr* src_addr, socklen_t* addr_len)
+      __overloadable {
   size_t bos = __bos0(buf);
 
-#if !defined(__clang__)
+  if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+    return __call_bypassing_fortify(recvfrom)(fd, buf, len, flags, src_addr,
+              addr_len);
+  }
+
+  return __recvfrom_chk(fd, buf, len, bos, flags, src_addr, addr_len);
+}
+#endif /* __ANDROID_API__ >= __ANDROID_API_N__ */
+
+__BIONIC_FORTIFY_INLINE
+ssize_t recv(int socket, void* const buf __pass_object_size, size_t len,
+             int flags) __overloadable {
+  return recvfrom(socket, buf, len, flags, NULL, 0);
+}
+
+#else /* defined(__clang__) */
+ssize_t __recvfrom_real(int, void*, size_t, int, struct sockaddr*, socklen_t*) __RENAME(recvfrom);
+__errordecl(__recvfrom_error, "recvfrom called with size bigger than buffer");
+
+#if __ANDROID_API__ >= __ANDROID_API_N__
+__BIONIC_FORTIFY_INLINE
+ssize_t recvfrom(int fd, void* buf, size_t len, int flags,
+                 struct sockaddr* src_addr, socklen_t* addr_len) {
+  size_t bos = __bos0(buf);
+
   if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
     return __recvfrom_real(fd, buf, len, flags, src_addr, addr_len);
   }
@@ -347,7 +381,6 @@
   if (__builtin_constant_p(len) && (len > bos)) {
     __recvfrom_error();
   }
-#endif
 
   return __recvfrom_chk(fd, buf, len, bos, flags, src_addr, addr_len);
 }
@@ -358,6 +391,8 @@
   return recvfrom(socket, buf, len, flags, NULL, 0);
 }
 
+#endif /* defined(__clang__) */
+
 #endif /* __BIONIC_FORTIFY */
 
 #undef __socketcall