libc fortify: make socket.h and stdlib.h use diagnose_if

Since realpath no longer needs to be overloaded, we can restore the
upstream source to purity. We'll be able to do this with most of the
other functions when we pull a newer clang in.

Bug: 12231437
Test: m checkbuild on bionic internal master; CtsBionicTestCases show
no new failures.

Change-Id: I484221bba0b291273fece23d2be2f5f9fd713d2c
This commit is contained in:
George Burgess IV 2017-07-31 21:21:10 -07:00
parent aa8f766bf0
commit 54f5d8331f
5 changed files with 70 additions and 65 deletions

View file

@ -37,64 +37,55 @@ ssize_t __recvfrom_chk(int, void*, size_t, size_t, int, struct sockaddr*,
#if defined(__BIONIC_FORTIFY)
#define __recvfrom_bad_size "recvfrom called with size bigger than buffer"
#define __sendto_bad_size "sendto called with size bigger than buffer"
#define __recvfrom_bad_size "'recvfrom' called with size bigger than buffer"
#define __sendto_bad_size "'sendto' called with size bigger than buffer"
#if defined(__clang__)
#if __ANDROID_API__ >= __ANDROID_API_N__
__BIONIC_ERROR_FUNCTION_VISIBILITY
ssize_t recvfrom(int fd, void* const buf __pass_object_size0, 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(__recvfrom_bad_size);
__BIONIC_FORTIFY_INLINE
ssize_t recvfrom(int fd, void* const buf __pass_object_size0, size_t len,
int flags, struct sockaddr* src_addr, socklen_t* addr_len)
__overloadable {
ssize_t recvfrom(int fd, void* const buf __pass_object_size0, size_t len, int flags, struct sockaddr* src_addr, socklen_t* addr_len)
__overloadable
__clang_error_if(__bos(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE && __bos(buf) < len,
__recvfrom_bad_size) {
size_t bos = __bos0(buf);
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
return __call_bypassing_fortify(recvfrom)(fd, buf, len, flags, src_addr,
addr_len);
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__ */
#if __ANDROID_API__ >= __ANDROID_API_N_MR1__
__BIONIC_ERROR_FUNCTION_VISIBILITY
ssize_t sendto(int fd, const void* buf, size_t len, int flags,
const struct sockaddr* dest_addr, socklen_t addr_len)
__overloadable
__enable_if(__bos0(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
__bos0(buf) < len, "selected when the buffer is too small")
__errorattr(__sendto_bad_size);
__BIONIC_FORTIFY_INLINE
ssize_t sendto(int fd, const void* const buf __pass_object_size0, size_t len,
int flags, const struct sockaddr* dest_addr, socklen_t addr_len)
__overloadable {
ssize_t sendto(int fd, const void* const buf __pass_object_size0, size_t len, int flags, const struct sockaddr* dest_addr, socklen_t addr_len)
__overloadable
__clang_error_if(__bos0(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE && __bos0(buf) < len,
__sendto_bad_size) {
size_t bos = __bos0(buf);
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
return __call_bypassing_fortify(sendto)(fd, buf, len, flags, dest_addr,
addr_len);
return __call_bypassing_fortify(sendto)(fd, buf, len, flags, dest_addr, addr_len);
}
return __sendto_chk(fd, buf, len, bos, flags, dest_addr, addr_len);
}
__BIONIC_ERROR_FUNCTION_VISIBILITY
ssize_t send(int socket, const void* buf, size_t len, int flags)
__overloadable
__enable_if(__bos0(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
__bos0(buf) < len, "selected when the buffer is too small")
__errorattr("send called with size bigger than buffer");
#endif /* __ANDROID_API__ >= __ANDROID_API_N_MR1__ */
__BIONIC_FORTIFY_INLINE
ssize_t recv(int socket, void* const buf __pass_object_size0, size_t len, int flags)
__overloadable
__clang_error_if(__bos0(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE && __bos0(buf) < len,
"'recv' called with size bigger than buffer") {
return recvfrom(socket, buf, len, flags, NULL, 0);
}
__BIONIC_FORTIFY_INLINE
ssize_t send(int socket, const void* const buf __pass_object_size0, size_t len, int flags)
__overloadable
__clang_error_if(__bos0(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE && __bos0(buf) < len,
"'send' called with size bigger than buffer") {
return sendto(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_bad_size);
@ -147,20 +138,17 @@ ssize_t sendto(int fd, const void* buf, size_t len, int flags,
}
#endif /* __ANDROID_API__ >= __ANDROID_API_N_MR1__ */
#endif /* defined(__clang__) */
#undef __recvfrom_bad_size
#undef __sendto_bad_size
__BIONIC_FORTIFY_INLINE
ssize_t recv(int socket, void* const buf __pass_object_size0, size_t len,
int flags) __overloadable {
ssize_t recv(int socket, void* buf, size_t len, int flags) {
return recvfrom(socket, buf, len, flags, NULL, 0);
}
__BIONIC_FORTIFY_INLINE
ssize_t send(int socket, const void* const buf __pass_object_size0, size_t len, int flags)
__overloadable {
ssize_t send(int socket, const void* buf, size_t len, int flags) {
return sendto(socket, buf, len, flags, NULL, 0);
}
#endif /* defined(__clang__) */
#undef __recvfrom_bad_size
#undef __sendto_bad_size
#endif /* __BIONIC_FORTIFY */

View file

@ -32,22 +32,16 @@
#if defined(__BIONIC_FORTIFY)
#define __realpath_buf_too_small_str \
"realpath output parameter must be NULL or a >= PATH_MAX bytes buffer"
"'realpath' output parameter must be NULL or a pointer to a buffer with >= PATH_MAX bytes"
/* PATH_MAX is unavailable without polluting the namespace, but it's always 4096 on Linux */
#define __PATH_MAX 4096
#if defined(__clang__)
__BIONIC_ERROR_FUNCTION_VISIBILITY
char* realpath(const char* path, char* resolved) __overloadable
__enable_if(__bos(resolved) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
__bos(resolved) < __PATH_MAX, __realpath_buf_too_small_str)
__errorattr(__realpath_buf_too_small_str);
/* No need for a FORTIFY version; the only things we can catch are at
* compile-time.
*/
char* realpath(const char* path, char* resolved)
__clang_error_if(__bos(resolved) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
__bos(resolved) < __PATH_MAX, __realpath_buf_too_small_str);
/* No need for a definition; the only issues we can catch are at compile-time. */
#else /* defined(__clang__) */

View file

@ -83,8 +83,7 @@ int atoi(const char*) __attribute_pure__;
long atol(const char*) __attribute_pure__;
long long atoll(const char*) __attribute_pure__;
char * realpath(const char *path, char *resolved) __overloadable
__RENAME_CLANG(realpath);
char* realpath(const char* path, char* resolved);
int system(const char *string);
void* bsearch(const void* key, const void* base0, size_t nmemb, size_t size,

View file

@ -48,7 +48,7 @@ __FBSDID("$FreeBSD$");
* in which case the path which caused trouble is left in (resolved).
*/
char *
realpath(const char * __restrict path, char * __restrict resolved) __overloadable
realpath(const char * __restrict path, char * __restrict resolved)
{
struct stat sb;
char *p, *q, *s;

View file

@ -183,11 +183,20 @@ void test_recvfrom() {
sockaddr_in addr;
// NOLINTNEXTLINE(whitespace/line_length)
// GCC: error: call to '__recvfrom_error' declared with attribute error: recvfrom called with size bigger than buffer
// CLANG: error: call to unavailable function 'recvfrom': recvfrom called with size bigger than buffer
// GCC: error: call to '__recvfrom_error' declared with attribute error: 'recvfrom' called with size bigger than buffer
// CLANG: error: 'recvfrom' called with size bigger than buffer
recvfrom(0, buf, 6, 0, reinterpret_cast<sockaddr*>(&addr), NULL);
}
void test_recv() {
char buf[4] = {0};
// NOLINTNEXTLINE(whitespace/line_length)
// GCC: error: call to '__recvfrom_error' declared with attribute error: 'recvfrom' called with size bigger than buffer
// CLANG: error: 'recv' called with size bigger than buffer
recv(0, buf, 6, 0);
}
void test_umask() {
// NOLINTNEXTLINE(whitespace/line_length)
// GCC: error: call to '__umask_invalid_mode' declared with attribute error: umask called with invalid mode
@ -316,8 +325,8 @@ void test_sendto() {
sockaddr_in addr;
// NOLINTNEXTLINE(whitespace/line_length)
// GCC: error: call to '__sendto_error' declared with attribute error: sendto called with size bigger than buffer
// CLANG: error: call to unavailable function 'sendto': sendto called with size bigger than buffer
// GCC: error: call to '__sendto_error' declared with attribute error: 'sendto' called with size bigger than buffer
// CLANG: error: 'sendto' called with size bigger than buffer
sendto(0, buf, 6, 0, reinterpret_cast<sockaddr*>(&addr), sizeof(sockaddr_in));
}
@ -325,7 +334,22 @@ void test_send() {
char buf[4] = {0};
// NOLINTNEXTLINE(whitespace/line_length)
// GCC: error: call to '__sendto_error' declared with attribute error: sendto called with size bigger than buffer
// CLANG: error: call to unavailable function 'send': send called with size bigger than buffer
// GCC: error: call to '__sendto_error' declared with attribute error: 'sendto' called with size bigger than buffer
// CLANG: error: 'send' called with size bigger than buffer
send(0, buf, 6, 0);
}
void test_realpath() {
char buf[4] = {0};
// NOLINTNEXTLINE(whitespace/line_length)
// GCC: error: call to '__realpath_size_error' declared with attribute error: 'realpath' output parameter must be NULL or a pointer to a buffer with >= PATH_MAX bytes
// NOLINTNEXTLINE(whitespace/line_length)
// CLANG: error: 'realpath' output parameter must be NULL or a pointer to a buffer with >= PATH_MAX bytes
realpath(".", buf);
// This is fine.
realpath(".", NULL);
// FIXME: But we should warn on this.
realpath(NULL, buf);
}