diff --git a/compiler-rt/lib/dfsan/dfsan_custom.cpp b/compiler-rt/lib/dfsan/dfsan_custom.cpp --- a/compiler-rt/lib/dfsan/dfsan_custom.cpp +++ b/compiler-rt/lib/dfsan/dfsan_custom.cpp @@ -1048,14 +1048,34 @@ } SANITIZER_INTERFACE_ATTRIBUTE -long int __dfsw_strtol(const char *nptr, char **endptr, int base, - dfsan_label nptr_label, dfsan_label endptr_label, - dfsan_label base_label, dfsan_label *ret_label) { - char *tmp_endptr; - long int ret = strtol(nptr, &tmp_endptr, base); - if (endptr) { - *endptr = tmp_endptr; +char *__dfso_strcpy(char *dest, const char *src, dfsan_label dst_label, + dfsan_label src_label, dfsan_label *ret_label, + dfsan_origin dst_origin, dfsan_origin src_origin, + dfsan_origin *ret_origin) { + char *ret = strcpy(dest, src); // NOLINT + if (ret) { + size_t str_len = strlen(src) + 1; + dfsan_mem_origin_transfer(dest, src, str_len); + internal_memcpy(shadow_for(dest), shadow_for(src), + sizeof(dfsan_label) * str_len); } + *ret_label = dst_label; + *ret_origin = dst_origin; + return ret; +} + +static long int dfsan_strtol(const char *nptr, char **endptr, int base, + char **tmp_endptr) { + assert(tmp_endptr); + long int ret = strtol(nptr, tmp_endptr, base); + if (endptr) + *endptr = *tmp_endptr; + return ret; +} + +static void dfsan_strtolong_label(const char *nptr, const char *tmp_endptr, + dfsan_label base_label, + dfsan_label *ret_label) { if (tmp_endptr > nptr) { // If *tmp_endptr is '\0' include its label as well. *ret_label = dfsan_union( @@ -1064,18 +1084,58 @@ } else { *ret_label = 0; } +} + +static void dfsan_strtolong_origin(const char *nptr, const char *tmp_endptr, + dfsan_label base_label, + dfsan_label *ret_label, + dfsan_origin base_origin, + dfsan_origin *ret_origin) { + if (tmp_endptr > nptr) { + // When multiple inputs are tainted, we propagate one of its origins. + // Because checking if base_label is tainted does not need additional + // computation, we prefer to propagating base_origin. + *ret_origin = base_label + ? base_origin + : dfsan_read_origin_of_first_taint( + nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)); + } +} + +SANITIZER_INTERFACE_ATTRIBUTE +long int __dfsw_strtol(const char *nptr, char **endptr, int base, + dfsan_label nptr_label, dfsan_label endptr_label, + dfsan_label base_label, dfsan_label *ret_label) { + char *tmp_endptr; + long int ret = dfsan_strtol(nptr, endptr, base, &tmp_endptr); + dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); return ret; } SANITIZER_INTERFACE_ATTRIBUTE -double __dfsw_strtod(const char *nptr, char **endptr, +long int __dfso_strtol(const char *nptr, char **endptr, int base, dfsan_label nptr_label, dfsan_label endptr_label, - dfsan_label *ret_label) { + dfsan_label base_label, dfsan_label *ret_label, + dfsan_origin nptr_origin, dfsan_origin endptr_origin, + dfsan_origin base_origin, dfsan_origin *ret_origin) { char *tmp_endptr; - double ret = strtod(nptr, &tmp_endptr); - if (endptr) { - *endptr = tmp_endptr; - } + long int ret = dfsan_strtol(nptr, endptr, base, &tmp_endptr); + dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); + dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin, + ret_origin); + return ret; +} + +static double dfsan_strtod(const char *nptr, char **endptr, char **tmp_endptr) { + assert(tmp_endptr); + double ret = strtod(nptr, tmp_endptr); + if (endptr) + *endptr = *tmp_endptr; + return ret; +} + +static void dfsan_strtod_label(const char *nptr, const char *tmp_endptr, + dfsan_label *ret_label) { if (tmp_endptr > nptr) { // If *tmp_endptr is '\0' include its label as well. *ret_label = dfsan_read_label( @@ -1084,46 +1144,109 @@ } else { *ret_label = 0; } +} + +SANITIZER_INTERFACE_ATTRIBUTE +double __dfsw_strtod(const char *nptr, char **endptr, dfsan_label nptr_label, + dfsan_label endptr_label, dfsan_label *ret_label) { + char *tmp_endptr; + double ret = dfsan_strtod(nptr, endptr, &tmp_endptr); + dfsan_strtod_label(nptr, tmp_endptr, ret_label); return ret; } SANITIZER_INTERFACE_ATTRIBUTE -long long int __dfsw_strtoll(const char *nptr, char **endptr, int base, - dfsan_label nptr_label, dfsan_label endptr_label, - dfsan_label base_label, dfsan_label *ret_label) { +double __dfso_strtod(const char *nptr, char **endptr, dfsan_label nptr_label, + dfsan_label endptr_label, dfsan_label *ret_label, + dfsan_origin nptr_origin, dfsan_origin endptr_origin, + dfsan_origin *ret_origin) { char *tmp_endptr; - long long int ret = strtoll(nptr, &tmp_endptr, base); - if (endptr) { - *endptr = tmp_endptr; - } + double ret = dfsan_strtod(nptr, endptr, &tmp_endptr); + dfsan_strtod_label(nptr, tmp_endptr, ret_label); if (tmp_endptr > nptr) { // If *tmp_endptr is '\0' include its label as well. - *ret_label = dfsan_union( - base_label, - dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1))); + *ret_origin = dfsan_read_origin_of_first_taint( + nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)); } else { - *ret_label = 0; + *ret_origin = 0; } return ret; } +static long long int dfsan_strtoll(const char *nptr, char **endptr, int base, + char **tmp_endptr) { + assert(tmp_endptr); + long long int ret = strtoll(nptr, tmp_endptr, base); + if (endptr) + *endptr = *tmp_endptr; + return ret; +} + +SANITIZER_INTERFACE_ATTRIBUTE +long long int __dfsw_strtoll(const char *nptr, char **endptr, int base, + dfsan_label nptr_label, dfsan_label endptr_label, + dfsan_label base_label, dfsan_label *ret_label) { + char *tmp_endptr; + long long int ret = dfsan_strtoll(nptr, endptr, base, &tmp_endptr); + dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); + return ret; +} + +SANITIZER_INTERFACE_ATTRIBUTE +long long int __dfso_strtoll(const char *nptr, char **endptr, int base, + dfsan_label nptr_label, dfsan_label endptr_label, + dfsan_label base_label, dfsan_label *ret_label, + dfsan_origin nptr_origin, + dfsan_origin endptr_origin, + dfsan_origin base_origin, + dfsan_origin *ret_origin) { + char *tmp_endptr; + long long int ret = dfsan_strtoll(nptr, endptr, base, &tmp_endptr); + dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); + dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin, + ret_origin); + return ret; +} + +static unsigned long int dfsan_strtoul(const char *nptr, char **endptr, + int base, char **tmp_endptr) { + assert(tmp_endptr); + unsigned long int ret = strtoul(nptr, tmp_endptr, base); + if (endptr) + *endptr = *tmp_endptr; + return ret; +} + SANITIZER_INTERFACE_ATTRIBUTE unsigned long int __dfsw_strtoul(const char *nptr, char **endptr, int base, dfsan_label nptr_label, dfsan_label endptr_label, dfsan_label base_label, dfsan_label *ret_label) { char *tmp_endptr; - unsigned long int ret = strtoul(nptr, &tmp_endptr, base); - if (endptr) { - *endptr = tmp_endptr; - } - if (tmp_endptr > nptr) { - // If *tmp_endptr is '\0' include its label as well. - *ret_label = dfsan_union( - base_label, - dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1))); - } else { - *ret_label = 0; - } + unsigned long int ret = dfsan_strtoul(nptr, endptr, base, &tmp_endptr); + dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); + return ret; +} + +SANITIZER_INTERFACE_ATTRIBUTE +unsigned long int __dfso_strtoul( + const char *nptr, char **endptr, int base, dfsan_label nptr_label, + dfsan_label endptr_label, dfsan_label base_label, dfsan_label *ret_label, + dfsan_origin nptr_origin, dfsan_origin endptr_origin, + dfsan_origin base_origin, dfsan_origin *ret_origin) { + char *tmp_endptr; + unsigned long int ret = dfsan_strtoul(nptr, endptr, base, &tmp_endptr); + dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); + dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin, + ret_origin); + return ret; +} + +static long long unsigned int dfsan_strtoull(const char *nptr, char **endptr, + int base, char **tmp_endptr) { + assert(tmp_endptr); + long long unsigned int ret = strtoull(nptr, tmp_endptr, base); + if (endptr) + *endptr = *tmp_endptr; return ret; } @@ -1134,18 +1257,22 @@ dfsan_label base_label, dfsan_label *ret_label) { char *tmp_endptr; - long long unsigned int ret = strtoull(nptr, &tmp_endptr, base); - if (endptr) { - *endptr = tmp_endptr; - } - if (tmp_endptr > nptr) { - // If *tmp_endptr is '\0' include its label as well. - *ret_label = dfsan_union( - base_label, - dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1))); - } else { - *ret_label = 0; - } + long long unsigned int ret = dfsan_strtoull(nptr, endptr, base, &tmp_endptr); + dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); + return ret; +} + +SANITIZER_INTERFACE_ATTRIBUTE +long long unsigned int __dfso_strtoull( + const char *nptr, char **endptr, int base, dfsan_label nptr_label, + dfsan_label endptr_label, dfsan_label base_label, dfsan_label *ret_label, + dfsan_origin nptr_origin, dfsan_origin endptr_origin, + dfsan_origin base_origin, dfsan_origin *ret_origin) { + char *tmp_endptr; + long long unsigned int ret = dfsan_strtoull(nptr, endptr, base, &tmp_endptr); + dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); + dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin, + ret_origin); return ret; } @@ -1480,6 +1607,14 @@ return ret; } +SANITIZER_INTERFACE_ATTRIBUTE +int __dfso_gettimeofday(struct timeval *tv, struct timezone *tz, + dfsan_label tv_label, dfsan_label tz_label, + dfsan_label *ret_label, dfsan_origin tv_origin, + dfsan_origin tz_origin, dfsan_origin *ret_origin) { + return __dfsw_gettimeofday(tv, tz, tv_label, tz_label, ret_label); +} + SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_memchr(void *s, int c, size_t n, dfsan_label s_label, dfsan_label c_label, @@ -1498,6 +1633,24 @@ return ret; } +SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_memchr( + void *s, int c, size_t n, dfsan_label s_label, dfsan_label c_label, + dfsan_label n_label, dfsan_label *ret_label, dfsan_origin s_origin, + dfsan_origin c_origin, dfsan_origin n_origin, dfsan_origin *ret_origin) { + void *ret = __dfsw_memchr(s, c, n, s_label, c_label, n_label, ret_label); + if (flags().strict_data_dependencies) { + if (ret) + *ret_origin = s_origin; + } else { + size_t len = + ret ? reinterpret_cast(ret) - reinterpret_cast(s) + 1 + : n; + dfsan_origin o = dfsan_read_origin_of_first_taint(s, len); + *ret_origin = o ? o : (s_label ? s_origin : c_origin); + } + return ret; +} + SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strrchr(char *s, int c, dfsan_label s_label, dfsan_label c_label, @@ -1514,6 +1667,23 @@ return ret; } +SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strrchr( + char *s, int c, dfsan_label s_label, dfsan_label c_label, + dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin, + dfsan_origin *ret_origin) { + char *ret = __dfsw_strrchr(s, c, s_label, c_label, ret_label); + if (flags().strict_data_dependencies) { + if (ret) + *ret_origin = s_origin; + } else { + size_t s_len = strlen(s) + 1; + dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_len); + *ret_origin = o ? o : (s_label ? s_origin : c_origin); + } + + return ret; +} + SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strstr(char *haystack, char *needle, dfsan_label haystack_label, dfsan_label needle_label, @@ -1532,6 +1702,33 @@ return ret; } +SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strstr(char *haystack, char *needle, + dfsan_label haystack_label, + dfsan_label needle_label, + dfsan_label *ret_label, + dfsan_origin haystack_origin, + dfsan_origin needle_origin, + dfsan_origin *ret_origin) { + char *ret = + __dfsw_strstr(haystack, needle, haystack_label, needle_label, ret_label); + if (flags().strict_data_dependencies) { + if (ret) + *ret_origin = haystack_origin; + } else { + size_t needle_len = strlen(needle); + size_t len = ret ? ret + needle_len - haystack : strlen(haystack) + 1; + dfsan_origin o = dfsan_read_origin_of_first_taint(haystack, len); + if (o) { + *ret_origin = o; + } else { + o = dfsan_read_origin_of_first_taint(needle, needle_len + 1); + *ret_origin = o ? o : (haystack_label ? haystack_origin : needle_origin); + } + } + + return ret; +} + SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_nanosleep(const struct timespec *req, struct timespec *rem, dfsan_label req_label, @@ -1546,6 +1743,13 @@ return ret; } +SANITIZER_INTERFACE_ATTRIBUTE int __dfso_nanosleep( + const struct timespec *req, struct timespec *rem, dfsan_label req_label, + dfsan_label rem_label, dfsan_label *ret_label, dfsan_origin req_origin, + dfsan_origin rem_origin, dfsan_origin *ret_origin) { + return __dfsw_nanosleep(req, rem, req_label, rem_label, ret_label); +} + static void clear_msghdr_labels(size_t bytes_written, struct msghdr *msg) { dfsan_set_label(0, msg, sizeof(*msg)); dfsan_set_label(0, msg->msg_name, msg->msg_namelen); @@ -1574,6 +1778,19 @@ return ret; } +SANITIZER_INTERFACE_ATTRIBUTE int __dfso_recvmmsg( + int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, + struct timespec *timeout, dfsan_label sockfd_label, + dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label, + dfsan_label timeout_label, dfsan_label *ret_label, + dfsan_origin sockfd_origin, dfsan_origin msgvec_origin, + dfsan_origin vlen_origin, dfsan_origin flags_origin, + dfsan_origin timeout_origin, dfsan_origin *ret_origin) { + return __dfsw_recvmmsg(sockfd, msgvec, vlen, flags, timeout, sockfd_label, + msgvec_label, vlen_label, flags_label, timeout_label, + ret_label); +} + SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfsw_recvmsg( int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label, dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label) { @@ -1584,6 +1801,15 @@ return ret; } +SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_recvmsg( + int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label, + dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label, + dfsan_origin sockfd_origin, dfsan_origin msg_origin, + dfsan_origin flags_origin, dfsan_origin *ret_origin) { + return __dfsw_recvmsg(sockfd, msg, flags, sockfd_label, msg_label, + flags_label, ret_label); +} + SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_socketpair(int domain, int type, int protocol, int sv[2], dfsan_label domain_label, dfsan_label type_label, @@ -1597,6 +1823,16 @@ return ret; } +SANITIZER_INTERFACE_ATTRIBUTE int __dfso_socketpair( + int domain, int type, int protocol, int sv[2], dfsan_label domain_label, + dfsan_label type_label, dfsan_label protocol_label, dfsan_label sv_label, + dfsan_label *ret_label, dfsan_origin domain_origin, + dfsan_origin type_origin, dfsan_origin protocol_origin, + dfsan_origin sv_origin, dfsan_origin *ret_origin) { + return __dfsw_socketpair(domain, type, protocol, sv, domain_label, type_label, + protocol_label, sv_label, ret_label); +} + SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockopt( int sockfd, int level, int optname, void *optval, socklen_t *optlen, dfsan_label sockfd_label, dfsan_label level_label, @@ -1611,6 +1847,19 @@ return ret; } +SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockopt( + int sockfd, int level, int optname, void *optval, socklen_t *optlen, + dfsan_label sockfd_label, dfsan_label level_label, + dfsan_label optname_label, dfsan_label optval_label, + dfsan_label optlen_label, dfsan_label *ret_label, + dfsan_origin sockfd_origin, dfsan_origin level_origin, + dfsan_origin optname_origin, dfsan_origin optval_origin, + dfsan_origin optlen_origin, dfsan_origin *ret_origin) { + return __dfsw_getsockopt(sockfd, level, optname, optval, optlen, sockfd_label, + level_label, optname_label, optval_label, + optlen_label, ret_label); +} + SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockname( int sockfd, struct sockaddr *addr, socklen_t *addrlen, dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label, @@ -1626,6 +1875,16 @@ return ret; } +SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockname( + int sockfd, struct sockaddr *addr, socklen_t *addrlen, + dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label, + dfsan_label *ret_label, dfsan_origin sockfd_origin, + dfsan_origin addr_origin, dfsan_origin addrlen_origin, + dfsan_origin *ret_origin) { + return __dfsw_getsockname(sockfd, addr, addrlen, sockfd_label, addr_label, + addrlen_label, ret_label); +} + SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getpeername( int sockfd, struct sockaddr *addr, socklen_t *addrlen, dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label, @@ -1641,6 +1900,16 @@ return ret; } +SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getpeername( + int sockfd, struct sockaddr *addr, socklen_t *addrlen, + dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label, + dfsan_label *ret_label, dfsan_origin sockfd_origin, + dfsan_origin addr_origin, dfsan_origin addrlen_origin, + dfsan_origin *ret_origin) { + return __dfsw_getpeername(sockfd, addr, addrlen, sockfd_label, addr_label, + addrlen_label, ret_label); +} + // Type of the trampoline function passed to the custom version of // dfsan_set_write_callback. typedef void (*write_trampoline_t)( @@ -1802,6 +2071,7 @@ // positional arguments. static int format_buffer(char *str, size_t size, const char *fmt, dfsan_label *va_labels, dfsan_label *ret_label, + dfsan_origin *va_origins, dfsan_origin *ret_origin, va_list ap) { Formatter formatter(str, fmt, size); @@ -1857,8 +2127,13 @@ default: retval = formatter.format(va_arg(ap, int)); } - dfsan_set_label(*va_labels++, formatter.str_cur(), - formatter.num_written_bytes(retval)); + if (va_origins == nullptr) + dfsan_set_label(*va_labels++, formatter.str_cur(), + formatter.num_written_bytes(retval)); + else + dfsan_set_label_origin(*va_labels++, *va_origins++, + formatter.str_cur(), + formatter.num_written_bytes(retval)); end_fmt = true; break; @@ -1875,21 +2150,36 @@ } else { retval = formatter.format(va_arg(ap, double)); } - dfsan_set_label(*va_labels++, formatter.str_cur(), - formatter.num_written_bytes(retval)); + if (va_origins == nullptr) + dfsan_set_label(*va_labels++, formatter.str_cur(), + formatter.num_written_bytes(retval)); + else + dfsan_set_label_origin(*va_labels++, *va_origins++, + formatter.str_cur(), + formatter.num_written_bytes(retval)); end_fmt = true; break; case 'c': retval = formatter.format(va_arg(ap, int)); - dfsan_set_label(*va_labels++, formatter.str_cur(), - formatter.num_written_bytes(retval)); + if (va_origins == nullptr) + dfsan_set_label(*va_labels++, formatter.str_cur(), + formatter.num_written_bytes(retval)); + else + dfsan_set_label_origin(*va_labels++, *va_origins++, + formatter.str_cur(), + formatter.num_written_bytes(retval)); end_fmt = true; break; case 's': { char *arg = va_arg(ap, char *); retval = formatter.format(arg); + if (va_origins) { + va_origins++; + dfsan_mem_origin_transfer(formatter.str_cur(), arg, + formatter.num_written_bytes(retval)); + } va_labels++; internal_memcpy(shadow_for(formatter.str_cur()), shadow_for(arg), sizeof(dfsan_label) * @@ -1900,8 +2190,13 @@ case 'p': retval = formatter.format(va_arg(ap, void *)); - dfsan_set_label(*va_labels++, formatter.str_cur(), - formatter.num_written_bytes(retval)); + if (va_origins == nullptr) + dfsan_set_label(*va_labels++, formatter.str_cur(), + formatter.num_written_bytes(retval)); + else + dfsan_set_label_origin(*va_labels++, *va_origins++, + formatter.str_cur(), + formatter.num_written_bytes(retval)); end_fmt = true; break; @@ -1909,6 +2204,8 @@ int *ptr = va_arg(ap, int *); *ptr = (int)formatter.str_off; va_labels++; + if (va_origins) + va_origins++; dfsan_set_label(0, ptr, sizeof(ptr)); end_fmt = true; break; @@ -1924,6 +2221,8 @@ case '*': formatter.width = va_arg(ap, int); va_labels++; + if (va_origins) + va_origins++; break; default: @@ -1941,6 +2240,8 @@ } *ret_label = 0; + if (ret_origin) + *ret_origin = 0; // Number of bytes written in total. return formatter.str_off; @@ -1953,7 +2254,22 @@ dfsan_label *ret_label, ...) { va_list ap; va_start(ap, ret_label); - int ret = format_buffer(str, ~0ul, format, va_labels, ret_label, ap); + int ret = format_buffer(str, ~0ul, format, va_labels, ret_label, nullptr, + nullptr, ap); + va_end(ap); + return ret; +} + +SANITIZER_INTERFACE_ATTRIBUTE +int __dfso_sprintf(char *str, const char *format, dfsan_label str_label, + dfsan_label format_label, dfsan_label *va_labels, + dfsan_label *ret_label, dfsan_origin str_origin, + dfsan_origin format_origin, dfsan_origin *va_origins, + dfsan_origin *ret_origin, ...) { + va_list ap; + va_start(ap, ret_origin); + int ret = format_buffer(str, ~0ul, format, va_labels, ret_label, va_origins, + ret_origin, ap); va_end(ap); return ret; } @@ -1965,7 +2281,23 @@ dfsan_label *ret_label, ...) { va_list ap; va_start(ap, ret_label); - int ret = format_buffer(str, size, format, va_labels, ret_label, ap); + int ret = format_buffer(str, size, format, va_labels, ret_label, nullptr, + nullptr, ap); + va_end(ap); + return ret; +} + +SANITIZER_INTERFACE_ATTRIBUTE +int __dfso_snprintf(char *str, size_t size, const char *format, + dfsan_label str_label, dfsan_label size_label, + dfsan_label format_label, dfsan_label *va_labels, + dfsan_label *ret_label, dfsan_origin str_origin, + dfsan_origin size_origin, dfsan_origin format_origin, + dfsan_origin *va_origins, dfsan_origin *ret_origin, ...) { + va_list ap; + va_start(ap, ret_origin); + int ret = format_buffer(str, size, format, va_labels, ret_label, va_origins, + ret_origin, ap); va_end(ap); return ret; } diff --git a/compiler-rt/test/dfsan/custom.cpp b/compiler-rt/test/dfsan/custom.cpp --- a/compiler-rt/test/dfsan/custom.cpp +++ b/compiler-rt/test/dfsan/custom.cpp @@ -600,7 +600,6 @@ free(crv); } -#if !defined(ORIGIN_TRACKING) void test_recvmmsg() { int sockfds[2]; int ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, sockfds); @@ -638,6 +637,9 @@ dfsan_set_label(i_label, &rmmsg[1].msg_len, sizeof(rmmsg[1].msg_len)); dfsan_set_label(i_label, &timeout, sizeof(timeout)); + dfsan_origin msg_len0_o = dfsan_get_origin((long)(rmmsg[0].msg_len)); + dfsan_origin msg_len1_o = dfsan_get_origin((long)(rmmsg[1].msg_len)); + // Receive messages and check labels. int received_msgs = recvmmsg(sockfds[1], rmmsg, 2, 0, &timeout); assert(received_msgs == sent_msgs); @@ -655,6 +657,9 @@ ASSERT_LABEL(timeout.tv_sec, i_label); ASSERT_LABEL(timeout.tv_nsec, i_label); + ASSERT_ORIGIN((long)(rmmsg[0].msg_len), msg_len0_o); + ASSERT_ORIGIN((long)(rmmsg[1].msg_len), msg_len1_o); + close(sockfds[0]); close(sockfds[1]); } @@ -682,6 +687,8 @@ dfsan_set_label(i_label, rbuf, sizeof(rbuf)); dfsan_set_label(i_label, &rmsg, sizeof(rmsg)); + DEFINE_AND_SAVE_ORIGINS(rmsg) + ssize_t received = recvmsg(sockfds[1], &rmsg, 0); assert(received == sent); assert(memcmp(sbuf, rbuf, 8) == 0); @@ -690,10 +697,11 @@ ASSERT_READ_ZERO_LABEL(&rbuf[0], 8); ASSERT_READ_LABEL(&rbuf[8], 1, i_label); + ASSERT_SAVED_ORIGINS(rmsg) + close(sockfds[0]); close(sockfds[1]); } -#endif // !defined(ORIGIN_TRACKING) void test_read() { char buf[16]; @@ -907,6 +915,7 @@ assert(getrusage(RUSAGE_SELF, &usage) == 0); ASSERT_READ_ZERO_LABEL(&usage, sizeof(usage)); } +#endif // !defined(ORIGIN_TRACKING) void test_strcpy() { char src[] = "hello world"; @@ -931,60 +940,128 @@ } void test_strtol() { - char buf[] = "1234578910"; + char non_number_buf[] = "ab "; char *endptr = NULL; + long int ret = strtol(non_number_buf, &endptr, 10); + assert(ret == 0); + assert(endptr == non_number_buf); + ASSERT_ZERO_LABEL(ret); + + char buf[] = "1234578910"; + int base = 10; + dfsan_set_label(k_label, &base, sizeof(base)); + ret = strtol(buf, &endptr, base); + assert(ret == 1234578910); + assert(endptr == buf + 10); + ASSERT_LABEL(ret, k_label); + ASSERT_EQ_ORIGIN(ret, base); + dfsan_set_label(i_label, buf + 1, 1); dfsan_set_label(j_label, buf + 10, 1); - long int ret = strtol(buf, &endptr, 10); + ret = strtol(buf, &endptr, 10); assert(ret == 1234578910); assert(endptr == buf + 10); ASSERT_LABEL(ret, i_j_label); + ASSERT_EQ_ORIGIN(ret, buf[1]); } void test_strtoll() { - char buf[] = "1234578910 "; + char non_number_buf[] = "ab "; char *endptr = NULL; + long long int ret = strtoll(non_number_buf, &endptr, 10); + assert(ret == 0); + assert(endptr == non_number_buf); + ASSERT_ZERO_LABEL(ret); + + char buf[] = "1234578910 "; + int base = 10; + dfsan_set_label(k_label, &base, sizeof(base)); + ret = strtoll(buf, &endptr, base); + assert(ret == 1234578910); + assert(endptr == buf + 10); + ASSERT_LABEL(ret, k_label); + ASSERT_EQ_ORIGIN(ret, base); + dfsan_set_label(i_label, buf + 1, 1); dfsan_set_label(j_label, buf + 2, 1); - long long int ret = strtoll(buf, &endptr, 10); + ret = strtoll(buf, &endptr, 10); assert(ret == 1234578910); assert(endptr == buf + 10); ASSERT_LABEL(ret, i_j_label); + ASSERT_EQ_ORIGIN(ret, buf[1]); } void test_strtoul() { - char buf[] = "ffffffffffffaa"; + char non_number_buf[] = "xy "; char *endptr = NULL; + long unsigned int ret = strtoul(non_number_buf, &endptr, 16); + assert(ret == 0); + assert(endptr == non_number_buf); + ASSERT_ZERO_LABEL(ret); + + char buf[] = "ffffffffffffaa"; + int base = 16; + dfsan_set_label(k_label, &base, sizeof(base)); + ret = strtoul(buf, &endptr, base); + assert(ret == 72057594037927850); + assert(endptr == buf + 14); + ASSERT_LABEL(ret, k_label); + ASSERT_EQ_ORIGIN(ret, base); + dfsan_set_label(i_label, buf + 1, 1); dfsan_set_label(j_label, buf + 2, 1); - long unsigned int ret = strtol(buf, &endptr, 16); + ret = strtoul(buf, &endptr, 16); assert(ret == 72057594037927850); assert(endptr == buf + 14); ASSERT_LABEL(ret, i_j_label); + ASSERT_EQ_ORIGIN(ret, buf[1]); } void test_strtoull() { - char buf[] = "ffffffffffffffaa"; + char non_number_buf[] = "xy "; char *endptr = NULL; + long long unsigned int ret = strtoull(non_number_buf, &endptr, 16); + assert(ret == 0); + assert(endptr == non_number_buf); + ASSERT_ZERO_LABEL(ret); + + char buf[] = "ffffffffffffffaa"; + int base = 16; + dfsan_set_label(k_label, &base, sizeof(base)); + ret = strtoull(buf, &endptr, base); + assert(ret == 0xffffffffffffffaa); + assert(endptr == buf + 16); + ASSERT_LABEL(ret, k_label); + ASSERT_EQ_ORIGIN(ret, base); + dfsan_set_label(i_label, buf + 1, 1); dfsan_set_label(j_label, buf + 2, 1); - long long unsigned int ret = strtoull(buf, &endptr, 16); + ret = strtoull(buf, &endptr, 16); assert(ret == 0xffffffffffffffaa); assert(endptr == buf + 16); ASSERT_LABEL(ret, i_j_label); + ASSERT_EQ_ORIGIN(ret, buf[1]); } void test_strtod() { - char buf[] = "12345.76 foo"; + char non_number_buf[] = "ab "; char *endptr = NULL; + double ret = strtod(non_number_buf, &endptr); + assert(ret == 0); + assert(endptr == non_number_buf); + ASSERT_ZERO_LABEL(ret); + + char buf[] = "12345.76 foo"; dfsan_set_label(i_label, buf + 1, 1); dfsan_set_label(j_label, buf + 6, 1); - double ret = strtod(buf, &endptr); + ret = strtod(buf, &endptr); assert(ret == 12345.76); assert(endptr == buf + 8); ASSERT_LABEL(ret, i_j_label); + ASSERT_EQ_ORIGIN(ret, buf[1]); } +#if !defined(ORIGIN_TRACKING) void test_time() { time_t t = 0; dfsan_set_label(i_label, &t, 1); @@ -1187,18 +1264,20 @@ ASSERT_SAVED_ORIGINS(old_altstack) } -#if !defined(ORIGIN_TRACKING) void test_gettimeofday() { struct timeval tv; struct timezone tz; dfsan_set_label(i_label, &tv, sizeof(tv)); dfsan_set_label(j_label, &tz, sizeof(tz)); + DEFINE_AND_SAVE_ORIGINS(tv) + DEFINE_AND_SAVE_ORIGINS(tz) int ret = gettimeofday(&tv, &tz); assert(ret == 0); ASSERT_READ_ZERO_LABEL(&tv, sizeof(tv)); ASSERT_READ_ZERO_LABEL(&tz, sizeof(tz)); + ASSERT_SAVED_ORIGINS(tv) + ASSERT_SAVED_ORIGINS(tz) } -#endif // !defined(ORIGIN_TRACKING) void *pthread_create_test_cb(void *p) { assert(p == (void *)1); @@ -1259,31 +1338,82 @@ ASSERT_ORIGIN(alignp, alignp_o); } -#if !defined(ORIGIN_TRACKING) void test_strrchr() { char str1[] = "str1str1"; + + char *p = str1; + dfsan_set_label(j_label, &p, sizeof(p)); + + char *rv = strrchr(p, 'r'); + assert(rv == &str1[6]); + ASSERT_LABEL(rv, j_label); + ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, p); + + char c = 'r'; + dfsan_set_label(k_label, &c, sizeof(c)); + rv = strrchr(str1, c); + assert(rv == &str1[6]); +#ifdef STRICT_DATA_DEPENDENCIES + ASSERT_ZERO_LABEL(rv); +#else + ASSERT_LABEL(rv, k_label); + ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, c); +#endif + dfsan_set_label(i_label, &str1[7], 1); - char *rv = strrchr(str1, 'r'); + rv = strrchr(str1, 'r'); assert(rv == &str1[6]); #ifdef STRICT_DATA_DEPENDENCIES ASSERT_ZERO_LABEL(rv); #else ASSERT_LABEL(rv, i_label); + ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, str1[7]); #endif } void test_strstr() { char str1[] = "str1str1"; + + char *p1 = str1; + dfsan_set_label(k_label, &p1, sizeof(p1)); + char *rv = strstr(p1, "1s"); + assert(rv == &str1[3]); + ASSERT_LABEL(rv, k_label); + ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, p1); + + char str2[] = "1s"; + char *p2 = str2; + dfsan_set_label(m_label, &p2, sizeof(p2)); + rv = strstr(str1, p2); + assert(rv == &str1[3]); +#ifdef STRICT_DATA_DEPENDENCIES + ASSERT_ZERO_LABEL(rv); +#else + ASSERT_LABEL(rv, m_label); + ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, p2); +#endif + + dfsan_set_label(n_label, &str2[0], 1); + rv = strstr(str1, str2); + assert(rv == &str1[3]); +#ifdef STRICT_DATA_DEPENDENCIES + ASSERT_ZERO_LABEL(rv); +#else + ASSERT_LABEL(rv, n_label); + ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, str2[0]); +#endif + dfsan_set_label(i_label, &str1[3], 1); dfsan_set_label(j_label, &str1[5], 1); - char *rv = strstr(str1, "1s"); + rv = strstr(str1, "1s"); assert(rv == &str1[3]); #ifdef STRICT_DATA_DEPENDENCIES ASSERT_ZERO_LABEL(rv); #else ASSERT_LABEL(rv, i_label); + ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, str1[3]); #endif rv = strstr(str1, "2s"); @@ -1292,9 +1422,9 @@ ASSERT_ZERO_LABEL(rv); #else ASSERT_LABEL(rv, i_j_label); + ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, str1[3]); #endif } -#endif // !defined(ORIGIN_TRACKING) void test_strpbrk() { char s[] = "abcdefg"; @@ -1360,7 +1490,6 @@ #endif } -#if !defined(ORIGIN_TRACKING) void test_memchr() { char str1[] = "str1"; dfsan_set_label(i_label, &str1[3], 1); @@ -1370,12 +1499,31 @@ assert(crv == &str1[2]); ASSERT_ZERO_LABEL(crv); + char c = 'r'; + dfsan_set_label(k_label, &c, sizeof(c)); + crv = (char *)memchr(str1, c, sizeof(str1)); + assert(crv == &str1[2]); +#ifdef STRICT_DATA_DEPENDENCIES + ASSERT_ZERO_LABEL(crv); +#else + ASSERT_LABEL(crv, k_label); + ASSERT_EQ_ORIGIN(crv, c); +#endif + + char *ptr = str1; + dfsan_set_label(k_label, &ptr, sizeof(ptr)); + crv = (char *)memchr(ptr, 'r', sizeof(str1)); + assert(crv == &str1[2]); + ASSERT_LABEL(crv, k_label); + ASSERT_EQ_ORIGIN(crv, ptr); + crv = (char *) memchr(str1, '1', sizeof(str1)); assert(crv == &str1[3]); #ifdef STRICT_DATA_DEPENDENCIES ASSERT_ZERO_LABEL(crv); #else ASSERT_LABEL(crv, i_label); + ASSERT_EQ_ORIGIN(crv, str1[3]); #endif crv = (char *) memchr(str1, 'x', sizeof(str1)); @@ -1384,6 +1532,7 @@ ASSERT_ZERO_LABEL(crv); #else ASSERT_LABEL(crv, i_j_label); + ASSERT_EQ_ORIGIN(crv, str1[3]); #endif } @@ -1396,12 +1545,14 @@ req.tv_sec = 1; req.tv_nsec = 0; dfsan_set_label(i_label, &rem, sizeof(rem)); + DEFINE_AND_SAVE_ORIGINS(rem) // non interrupted int rv = nanosleep(&req, &rem); assert(rv == 0); ASSERT_ZERO_LABEL(rv); ASSERT_READ_LABEL(&rem, 1, i_label); + ASSERT_SAVED_ORIGINS(rem) // interrupted by an alarm signal(SIGALRM, alarm_handler); @@ -1411,16 +1562,22 @@ assert(rv == -1); ASSERT_ZERO_LABEL(rv); ASSERT_READ_ZERO_LABEL(&rem, sizeof(rem)); + ASSERT_SAVED_ORIGINS(rem) } void test_socketpair() { int fd[2]; + dfsan_origin fd_o[2]; dfsan_set_label(i_label, fd, sizeof(fd)); + fd_o[0] = dfsan_get_origin((long)(fd[0])); + fd_o[1] = dfsan_get_origin((long)(fd[1])); int rv = socketpair(PF_LOCAL, SOCK_STREAM, 0, fd); assert(rv == 0); ASSERT_ZERO_LABEL(rv); ASSERT_READ_ZERO_LABEL(fd, sizeof(fd)); + ASSERT_ORIGIN(fd[0], fd_o[0]); + ASSERT_ORIGIN(fd[1], fd_o[1]); } void test_getpeername() { @@ -1432,6 +1589,8 @@ socklen_t addrlen = sizeof(addr); dfsan_set_label(i_label, &addr, addrlen); dfsan_set_label(i_label, &addrlen, sizeof(addrlen)); + DEFINE_AND_SAVE_ORIGINS(addr) + DEFINE_AND_SAVE_ORIGINS(addrlen) ret = getpeername(sockfds[0], &addr, &addrlen); assert(ret != -1); @@ -1440,6 +1599,8 @@ assert(addrlen < sizeof(addr)); ASSERT_READ_ZERO_LABEL(&addr, addrlen); ASSERT_READ_LABEL(((char *)&addr) + addrlen, 1, i_label); + ASSERT_SAVED_ORIGINS(addr) + ASSERT_SAVED_ORIGINS(addrlen) close(sockfds[0]); close(sockfds[1]); @@ -1453,7 +1614,8 @@ socklen_t addrlen = sizeof(addr); dfsan_set_label(i_label, &addr, addrlen); dfsan_set_label(i_label, &addrlen, sizeof(addrlen)); - + DEFINE_AND_SAVE_ORIGINS(addr) + DEFINE_AND_SAVE_ORIGINS(addrlen) int ret = getsockname(sockfd, &addr, &addrlen); assert(ret != -1); ASSERT_ZERO_LABEL(ret); @@ -1461,6 +1623,8 @@ assert(addrlen < sizeof(addr)); ASSERT_READ_ZERO_LABEL(&addr, addrlen); ASSERT_READ_LABEL(((char *)&addr) + addrlen, 1, i_label); + ASSERT_SAVED_ORIGINS(addr) + ASSERT_SAVED_ORIGINS(addrlen) close(sockfd); } @@ -1473,6 +1637,8 @@ socklen_t optlen = sizeof(optval); dfsan_set_label(i_label, &optval, sizeof(optval)); dfsan_set_label(i_label, &optlen, sizeof(optlen)); + DEFINE_AND_SAVE_ORIGINS(optval) + DEFINE_AND_SAVE_ORIGINS(optlen) int ret = getsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen); assert(ret != -1); assert(optlen == sizeof(int)); @@ -1482,10 +1648,11 @@ ASSERT_ZERO_LABEL(optlen); ASSERT_ZERO_LABEL(optval[0]); ASSERT_LABEL(optval[1], i_label); + ASSERT_SAVED_ORIGINS(optval) + ASSERT_SAVED_ORIGINS(optlen) close(sockfd); } -#endif // !defined(ORIGIN_TRACKING) void test_write() { int fd = open("/dev/null", O_WRONLY); @@ -1510,7 +1677,6 @@ close(fd); } -#if !defined(ORIGIN_TRACKING) template void test_sprintf_chunk(const char* expected, const char* format, T arg) { char buf[512]; @@ -1534,10 +1700,12 @@ // Labelled arg. dfsan_set_label(i_label, &arg, sizeof(arg)); + dfsan_origin a_o = dfsan_get_origin((long)(arg)); assert(sprintf(buf, padded_format, arg) == strlen(padded_expected)); assert(strcmp(buf, padded_expected) == 0); ASSERT_READ_LABEL(buf, 4, 0); ASSERT_READ_LABEL(buf + 4, strlen(padded_expected) - 8, i_label); + ASSERT_INIT_ORIGINS(buf + 4, strlen(padded_expected) - 8, a_o); ASSERT_READ_LABEL(buf + (strlen(padded_expected) - 4), 4, 0); } @@ -1561,8 +1729,11 @@ int m = 8; int d = 27; dfsan_set_label(k_label, (void *) (s + 1), 2); + dfsan_origin s_o = dfsan_get_origin((long)(s[1])); dfsan_set_label(i_label, &m, sizeof(m)); + dfsan_origin m_o = dfsan_get_origin((long)m); dfsan_set_label(j_label, &d, sizeof(d)); + dfsan_origin d_o = dfsan_get_origin((long)d); int n; int r = sprintf(buf, "hello %s, %-d/%d/%d %f %% %n%d", s, 2014, m, d, 12345.6781234, &n, 1000); @@ -1570,10 +1741,13 @@ assert(strcmp(buf, "hello world, 2014/8/27 12345.678123 % 1000") == 0); ASSERT_READ_LABEL(buf, 7, 0); ASSERT_READ_LABEL(buf + 7, 2, k_label); + ASSERT_INIT_ORIGINS(buf + 7, 2, s_o); ASSERT_READ_LABEL(buf + 9, 9, 0); ASSERT_READ_LABEL(buf + 18, 1, i_label); + ASSERT_INIT_ORIGINS(buf + 18, 1, m_o); ASSERT_READ_LABEL(buf + 19, 1, 0); ASSERT_READ_LABEL(buf + 20, 2, j_label); + ASSERT_INIT_ORIGINS(buf + 20, 2, d_o); ASSERT_READ_LABEL(buf + 22, 15, 0); ASSERT_LABEL(r, 0); assert(n == 38); @@ -1623,22 +1797,26 @@ int m = 8; int d = 27; dfsan_set_label(k_label, (void *) (s + 1), 2); + dfsan_origin s_o = dfsan_get_origin((long)(s[1])); dfsan_set_label(i_label, &y, sizeof(y)); + dfsan_origin y_o = dfsan_get_origin((long)y); dfsan_set_label(j_label, &m, sizeof(m)); - int r = snprintf(buf, 19, "hello %s, %-d/%d/%d %f", s, y, m, d, + dfsan_origin m_o = dfsan_get_origin((long)m); + int r = snprintf(buf, 19, "hello %s, %-d/ %d/%d %f", s, y, m, d, 12345.6781234); // The return value is the number of bytes that would have been written to // the final string if enough space had been available. - assert(r == 35); + assert(r == 38); assert(memcmp(buf, "hello world, 2014/", 19) == 0); ASSERT_READ_LABEL(buf, 7, 0); ASSERT_READ_LABEL(buf + 7, 2, k_label); + ASSERT_INIT_ORIGINS(buf + 7, 2, s_o); ASSERT_READ_LABEL(buf + 9, 4, 0); ASSERT_READ_LABEL(buf + 13, 4, i_label); + ASSERT_INIT_ORIGINS(buf + 13, 4, y_o); ASSERT_READ_LABEL(buf + 17, 2, 0); ASSERT_LABEL(r, 0); } -#endif // !defined(ORIGIN_TRACKING) // Tested by a seperate source file. This empty function is here to appease the // check-wrappers script. @@ -1683,32 +1861,36 @@ test_get_current_dir_name(); test_getcwd(); test_gethostname(); +#endif // !defined(ORIGIN_TRACKING) test_getpeername(); +#if !defined(ORIGIN_TRACKING) test_getpwuid_r(); test_getrlimit(); test_getrusage(); +#endif // !defined(ORIGIN_TRACKING) test_getsockname(); test_getsockopt(); test_gettimeofday(); +#if !defined(ORIGIN_TRACKING) test_inet_pton(); test_localtime_r(); - test_memchr(); #endif // !defined(ORIGIN_TRACKING) + test_memchr(); test_memcmp(); test_memcpy(); test_memmove(); test_memset(); -#if !defined(ORIGIN_TRACKING) test_nanosleep(); +#if !defined(ORIGIN_TRACKING) test_poll(); #endif // !defined(ORIGIN_TRACKING) test_pread(); test_pthread_create(); test_pthread_join(); test_read(); -#if !defined(ORIGIN_TRACKING) test_recvmmsg(); test_recvmsg(); +#if !defined(ORIGIN_TRACKING) test_sched_getaffinity(); test_select(); #endif // !defined(ORIGIN_TRACKING) @@ -1716,11 +1898,9 @@ test_signal(); test_sigaltstack(); test_sigemptyset(); -#if !defined(ORIGIN_TRACKING) test_snprintf(); test_socketpair(); test_sprintf(); -#endif // !defined(ORIGIN_TRACKING) test_stat(); test_strcasecmp(); test_strchr(); @@ -1735,7 +1915,6 @@ test_strncmp(); test_strncpy(); test_strpbrk(); -#if !defined(ORIGIN_TRACKING) test_strrchr(); test_strstr(); test_strtod(); @@ -1743,6 +1922,7 @@ test_strtoll(); test_strtoul(); test_strtoull(); +#if !defined(ORIGIN_TRACKING) test_time(); #endif // !defined(ORIGIN_TRACKING) test_write();