diff --git a/compiler-rt/lib/dfsan/dfsan.h b/compiler-rt/lib/dfsan/dfsan.h --- a/compiler-rt/lib/dfsan/dfsan.h +++ b/compiler-rt/lib/dfsan/dfsan.h @@ -48,6 +48,10 @@ // from the address addr. dfsan_origin dfsan_read_origin_of_first_taint(const void *addr, uptr size); +// Set the data within [addr, addr+size) with label and origin. +void dfsan_set_label_origin(dfsan_label label, dfsan_origin origin, void *addr, + uptr size); + // Copy or move the origins of the len bytes from src to dst. void dfsan_mem_origin_transfer(const void *dst, const void *src, uptr len); } // extern "C" diff --git a/compiler-rt/lib/dfsan/dfsan.cpp b/compiler-rt/lib/dfsan/dfsan.cpp --- a/compiler-rt/lib/dfsan/dfsan.cpp +++ b/compiler-rt/lib/dfsan/dfsan.cpp @@ -736,6 +736,13 @@ return GetOriginIfTainted((uptr)addr, size); } +SANITIZER_INTERFACE_ATTRIBUTE void dfsan_set_label_origin(dfsan_label label, + dfsan_origin origin, + void *addr, + uptr size) { + __dfsan_set_label(label, origin, addr, size); +} + extern "C" SANITIZER_INTERFACE_ATTRIBUTE const struct dfsan_label_info *dfsan_get_label_info(dfsan_label label) { return &__dfsan_label_info[label]; 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 @@ -470,6 +470,15 @@ return p; } +SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_calloc( + size_t nmemb, size_t size, dfsan_label nmemb_label, dfsan_label size_label, + dfsan_label *ret_label, dfsan_origin nmemb_origin, dfsan_origin size_origin, + dfsan_origin *ret_origin) { + void *p = __dfsw_calloc(nmemb, size, nmemb_label, size_label, ret_label); + *ret_origin = 0; + return p; +} + SANITIZER_INTERFACE_ATTRIBUTE size_t __dfsw_strlen(const char *s, dfsan_label s_label, dfsan_label *ret_label) { size_t ret = strlen(s); @@ -499,6 +508,11 @@ return internal_memmove(dest, src, n); } +static void *dfsan_memmove_with_origin(void *dest, const void *src, size_t n) { + dfsan_mem_origin_transfer(dest, src, n); + return dfsan_memmove(dest, src, n); +} + static void *dfsan_memcpy(void *dest, const void *src, size_t n) { dfsan_label *sdest = shadow_for(dest); const dfsan_label *ssrc = shadow_for(src); @@ -506,11 +520,22 @@ return internal_memcpy(dest, src, n); } +static void *dfsan_memcpy_with_origin(void *dest, const void *src, size_t n) { + dfsan_mem_origin_transfer(dest, src, n); + return dfsan_memcpy(dest, src, n); +} + static void dfsan_memset(void *s, int c, dfsan_label c_label, size_t n) { internal_memset(s, c, n); dfsan_set_label(c_label, s, n); } +static void dfsan_memset_with_origin(void *s, int c, dfsan_label c_label, + dfsan_origin c_origin, size_t n) { + internal_memset(s, c, n); + dfsan_set_label_origin(c_label, c_origin, s, n); +} + SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_memcpy(void *dest, const void *src, size_t n, dfsan_label dest_label, dfsan_label src_label, @@ -519,6 +544,17 @@ return dfsan_memcpy(dest, src, n); } +SANITIZER_INTERFACE_ATTRIBUTE +void *__dfso_memcpy(void *dest, const void *src, size_t n, + dfsan_label dest_label, dfsan_label src_label, + dfsan_label n_label, dfsan_label *ret_label, + dfsan_origin dest_origin, dfsan_origin src_origin, + dfsan_origin n_origin, dfsan_origin *ret_origin) { + *ret_label = dest_label; + *ret_origin = dest_origin; + return dfsan_memcpy_with_origin(dest, src, n); +} + SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_memmove(void *dest, const void *src, size_t n, dfsan_label dest_label, dfsan_label src_label, @@ -527,6 +563,17 @@ return dfsan_memmove(dest, src, n); } +SANITIZER_INTERFACE_ATTRIBUTE +void *__dfso_memmove(void *dest, const void *src, size_t n, + dfsan_label dest_label, dfsan_label src_label, + dfsan_label n_label, dfsan_label *ret_label, + dfsan_origin dest_origin, dfsan_origin src_origin, + dfsan_origin n_origin, dfsan_origin *ret_origin) { + *ret_label = dest_label; + *ret_origin = dest_origin; + return dfsan_memmove_with_origin(dest, src, n); +} + SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_memset(void *s, int c, size_t n, dfsan_label s_label, dfsan_label c_label, @@ -536,6 +583,18 @@ return s; } +SANITIZER_INTERFACE_ATTRIBUTE +void *__dfso_memset(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) { + dfsan_memset_with_origin(s, c, c_label, c_origin, n); + *ret_label = s_label; + *ret_origin = s_origin; + return s; +} + SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strcat(char *dest, const char *src, dfsan_label dest_label, dfsan_label src_label, @@ -550,6 +609,23 @@ return ret; } +SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strcat( + char *dest, const char *src, dfsan_label dest_label, dfsan_label src_label, + dfsan_label *ret_label, dfsan_origin dest_origin, dfsan_origin src_origin, + dfsan_origin *ret_origin) { + size_t dest_len = strlen(dest); + char *ret = strcat(dest, src); // NOLINT + dfsan_label *sdest = shadow_for(dest + dest_len); + const dfsan_label *ssrc = shadow_for(src); + size_t src_len = strlen(src); + dfsan_mem_origin_transfer(dest + dest_len, src, src_len); + internal_memcpy((void *)sdest, (const void *)ssrc, + src_len * sizeof(dfsan_label)); + *ret_label = dest_label; + *ret_origin = dest_origin; + return ret; +} + SANITIZER_INTERFACE_ATTRIBUTE char * __dfsw_strdup(const char *s, dfsan_label s_label, dfsan_label *ret_label) { size_t len = strlen(s); @@ -559,6 +635,19 @@ return static_cast(p); } +SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strdup(const char *s, + dfsan_label s_label, + dfsan_label *ret_label, + dfsan_origin s_origin, + dfsan_origin *ret_origin) { + size_t len = strlen(s); + void *p = malloc(len + 1); + dfsan_memcpy_with_origin(p, s, len + 1); + *ret_label = 0; + *ret_origin = 0; + return static_cast(p); +} + SANITIZER_INTERFACE_ATTRIBUTE char * __dfsw_strncpy(char *s1, const char *s2, size_t n, dfsan_label s1_label, dfsan_label s2_label, dfsan_label n_label, @@ -575,6 +664,24 @@ return s1; } +SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strncpy( + char *s1, const char *s2, size_t n, dfsan_label s1_label, + dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label, + dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin, + dfsan_origin *ret_origin) { + size_t len = strlen(s2); + if (len < n) { + dfsan_memcpy_with_origin(s1, s2, len + 1); + dfsan_memset_with_origin(s1 + len + 1, 0, 0, 0, n - len - 1); + } else { + dfsan_memcpy_with_origin(s1, s2, n); + } + + *ret_label = s1_label; + *ret_origin = s1_origin; + return s1; +} + SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfsw_pread(int fd, void *buf, size_t count, off_t offset, dfsan_label fd_label, dfsan_label buf_label, @@ -587,6 +694,17 @@ return ret; } +SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_pread( + int fd, void *buf, size_t count, off_t offset, dfsan_label fd_label, + dfsan_label buf_label, dfsan_label count_label, dfsan_label offset_label, + dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin, + dfsan_origin count_origin, dfsan_label offset_origin, + dfsan_origin *ret_origin) { + ssize_t ret = __dfsw_pread(fd, buf, count, offset, fd_label, buf_label, + count_label, offset_label, ret_label); + return ret; +} + SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfsw_read(int fd, void *buf, size_t count, dfsan_label fd_label, dfsan_label buf_label, @@ -599,6 +717,16 @@ return ret; } +SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_read( + int fd, void *buf, size_t count, dfsan_label fd_label, + dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label, + dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin, + dfsan_origin *ret_origin) { + ssize_t ret = + __dfsw_read(fd, buf, count, fd_label, buf_label, count_label, ret_label); + return ret; +} + SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_clock_gettime(clockid_t clk_id, struct timespec *tp, dfsan_label clk_id_label, @@ -611,7 +739,15 @@ return ret; } -static void unpoison(const void *ptr, uptr size) { +SANITIZER_INTERFACE_ATTRIBUTE int __dfso_clock_gettime( + clockid_t clk_id, struct timespec *tp, dfsan_label clk_id_label, + dfsan_label tp_label, dfsan_label *ret_label, dfsan_origin clk_id_origin, + dfsan_origin tp_origin, dfsan_origin *ret_origin) { + int ret = __dfsw_clock_gettime(clk_id, tp, clk_id_label, tp_label, ret_label); + return ret; +} + +static void dfsan_set_zero_label(const void *ptr, uptr size) { dfsan_set_label(0, const_cast(ptr), size); } @@ -624,11 +760,21 @@ void *handle = dlopen(filename, flag); link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE(handle); if (map) - ForEachMappedRegion(map, unpoison); + ForEachMappedRegion(map, dfsan_set_zero_label); *ret_label = 0; return handle; } +SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_dlopen( + const char *filename, int flag, dfsan_label filename_label, + dfsan_label flag_label, dfsan_label *ret_label, + dfsan_origin filename_origin, dfsan_origin flag_origin, + dfsan_origin *ret_origin) { + void *handle = + __dfsw_dlopen(filename, flag, filename_label, flag_label, ret_label); + return handle; +} + static void *DFsanThreadStartFunc(void *arg) { DFsanThread *t = (DFsanThread *)arg; SetCurrentThread(t); @@ -715,6 +861,17 @@ void *data; }; +struct dl_iterate_phdr_origin_info { + int (*callback_trampoline)(void *callback, struct dl_phdr_info *info, + size_t size, void *data, dfsan_label info_label, + dfsan_label size_label, dfsan_label data_label, + dfsan_label *ret_label, dfsan_origin info_origin, + dfsan_origin size_origin, dfsan_origin data_origin, + dfsan_origin *ret_origin); + void *callback; + void *data; +}; + int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size, void *data) { dl_iterate_phdr_info *dipi = (dl_iterate_phdr_info *)data; dfsan_set_label(0, *info); @@ -728,6 +885,21 @@ 0, &ret_label); } +int dl_iterate_phdr_origin_cb(struct dl_phdr_info *info, size_t size, + void *data) { + dl_iterate_phdr_origin_info *dipi = (dl_iterate_phdr_origin_info *)data; + dfsan_set_label(0, *info); + dfsan_set_label(0, const_cast(info->dlpi_name), + strlen(info->dlpi_name) + 1); + dfsan_set_label( + 0, const_cast(reinterpret_cast(info->dlpi_phdr)), + sizeof(*info->dlpi_phdr) * info->dlpi_phnum); + dfsan_label ret_label; + dfsan_origin ret_origin; + return dipi->callback_trampoline(dipi->callback, info, size, dipi->data, 0, 0, + 0, &ret_label, 0, 0, 0, &ret_origin); +} + SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr( int (*callback_trampoline)(void *callback, struct dl_phdr_info *info, size_t size, void *data, dfsan_label info_label, @@ -740,6 +912,23 @@ return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi); } +SANITIZER_INTERFACE_ATTRIBUTE int __dfso_dl_iterate_phdr( + int (*callback_trampoline)(void *callback, struct dl_phdr_info *info, + size_t size, void *data, dfsan_label info_label, + dfsan_label size_label, dfsan_label data_label, + dfsan_label *ret_label, dfsan_origin info_origin, + dfsan_origin size_origin, + dfsan_origin data_origin, + dfsan_origin *ret_origin), + void *callback, void *data, dfsan_label callback_label, + dfsan_label data_label, dfsan_label *ret_label, + dfsan_origin callback_origin, dfsan_origin data_origin, + dfsan_origin *ret_origin) { + dl_iterate_phdr_origin_info dipi = {callback_trampoline, callback, data}; + *ret_label = 0; + return dl_iterate_phdr(dl_iterate_phdr_origin_cb, &dipi); +} + // This function is only available for glibc 2.27 or newer. Mark it weak so // linking succeeds with older glibcs. SANITIZER_WEAK_ATTRIBUTE void _dl_get_tls_static_info(size_t *sizep, @@ -754,6 +943,13 @@ dfsan_set_label(0, alignp, sizeof(*alignp)); } +SANITIZER_INTERFACE_ATTRIBUTE void __dfso__dl_get_tls_static_info( + size_t *sizep, size_t *alignp, dfsan_label sizep_label, + dfsan_label alignp_label, dfsan_origin sizep_origin, + dfsan_origin alignp_origin) { + __dfsw__dl_get_tls_static_info(sizep, alignp, sizep_label, alignp_label); +} + SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label, dfsan_label buf_label, dfsan_label *ret_label) { 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 @@ -217,41 +217,68 @@ ASSERT_ZERO_LABEL(rv); } -#if !defined(ORIGIN_TRACKING) void test_memcpy() { char str1[] = "str1"; char str2[sizeof(str1)]; dfsan_set_label(i_label, &str1[3], 1); - ASSERT_ZERO_LABEL(memcpy(str2, str1, sizeof(str1))); + DEFINE_AND_SAVE_ORIGINS(str1) + + char *ptr2 = str2; + dfsan_set_label(j_label, &ptr2, sizeof(ptr2)); + + void *r = memcpy(ptr2, str1, sizeof(str1)); + ASSERT_LABEL(r, j_label); + ASSERT_EQ_ORIGIN(r, ptr2); assert(0 == memcmp(str2, str1, sizeof(str1))); ASSERT_ZERO_LABEL(str2[0]); ASSERT_LABEL(str2[3], i_label); + + for (int i = 0; i < sizeof(str2); ++i) { + if (!dfsan_get_label(str2[i])) + continue; + ASSERT_INIT_ORIGIN(&(str2[i]), str1_o[i]); + } } void test_memmove() { char str[] = "str1xx"; dfsan_set_label(i_label, &str[3], 1); - ASSERT_ZERO_LABEL(memmove(str + 2, str, 4)); + DEFINE_AND_SAVE_ORIGINS(str) + + char *ptr = str + 2; + dfsan_set_label(j_label, &ptr, sizeof(ptr)); + + void *r = memmove(ptr, str, 4); + ASSERT_LABEL(r, j_label); + ASSERT_EQ_ORIGIN(r, ptr); assert(0 == memcmp(str + 2, "str1", 4)); - for (int i = 0; i <= 4; ++i) - ASSERT_ZERO_LABEL(str[i]); + ASSERT_ZERO_LABEL(str[4]); ASSERT_LABEL(str[5], i_label); + + for (int i = 0; i < 4; ++i) { + if (!dfsan_get_label(ptr[i])) + continue; + ASSERT_INIT_ORIGIN(&(ptr[i]), str_o[i]); + } } void test_memset() { char buf[8]; int j = 'a'; + char *ptr = buf; dfsan_set_label(j_label, &j, sizeof(j)); - - ASSERT_ZERO_LABEL(memset(&buf, j, sizeof(buf))); + dfsan_set_label(k_label, &ptr, sizeof(ptr)); + void *ret = memset(ptr, j, sizeof(buf)); + ASSERT_LABEL(ret, k_label); + ASSERT_EQ_ORIGIN(ret, ptr); for (int i = 0; i < 8; ++i) { ASSERT_LABEL(buf[i], j_label); + ASSERT_EQ_ORIGIN(buf[i], j); assert(buf[i] == 'a'); } } -#endif // !defined(ORIGIN_TRACKING) void test_strcmp() { char str1[] = "str1", str2[] = "str2"; @@ -278,18 +305,34 @@ #endif } -#if !defined(ORIGIN_TRACKING) void test_strcat() { char src[] = "world"; + int volatile x = 0; // buffer to ensure src and dst do not share origins char dst[] = "hello \0 "; + int volatile y = 0; // buffer to ensure dst and p do not share origins char *p = dst; dfsan_set_label(k_label, &p, sizeof(p)); dfsan_set_label(i_label, src, sizeof(src)); dfsan_set_label(j_label, dst, sizeof(dst)); + dfsan_origin dst_o = dfsan_get_origin((long)dst[0]); char *ret = strcat(p, src); ASSERT_LABEL(ret, k_label); + ASSERT_EQ_ORIGIN(ret, p); assert(ret == dst); assert(strcmp(src, dst + 6) == 0); + // Origins are assigned for every 4 contiguous 4-aligned bytes. After + // appending src to dst, origins of src can overwrite origins of dst if their + // application adddresses are within [start_aligned_down, end_aligned_up). + // Other origins are not changed. + char *start_aligned_down = (char *)(((size_t)(dst + 6)) & ~3UL); + char *end_aligned_up = (char *)(((size_t)(dst + 11 + 4)) & ~3UL); + for (int i = 0; i < 12; ++i) { + if (dst + i < start_aligned_down || dst + i >= end_aligned_up) { + ASSERT_INIT_ORIGIN(&dst[i], dst_o); + } else { + ASSERT_INIT_ORIGIN_EQ_ORIGIN(&dst[i], src[0]); + } + } for (int i = 0; i < 6; ++i) { ASSERT_LABEL(dst[i], j_label); } @@ -299,7 +342,6 @@ } ASSERT_LABEL(dst[11], j_label); } -#endif // !defined(ORIGIN_TRACKING) void test_strlen() { char str1[] = "str1"; @@ -315,14 +357,22 @@ #endif } -#if !defined(ORIGIN_TRACKING) void test_strdup() { char str1[] = "str1"; dfsan_set_label(i_label, &str1[3], 1); + DEFINE_AND_SAVE_ORIGINS(str1) char *strd = strdup(str1); + ASSERT_ZERO_LABEL(strd); ASSERT_ZERO_LABEL(strd[0]); ASSERT_LABEL(strd[3], i_label); + + for (int i = 0; i < strlen(strd); ++i) { + if (!dfsan_get_label(strd[i])) + continue; + ASSERT_INIT_ORIGIN(&(strd[i]), str1_o[i]); + } + free(strd); } @@ -339,16 +389,29 @@ ASSERT_ZERO_LABEL(strd[1]); ASSERT_ZERO_LABEL(strd[2]); ASSERT_LABEL(strd[3], i_label); + ASSERT_INIT_ORIGIN_EQ_ORIGIN(&(strd[3]), str1[3]); - strd = strncpy(str2, str1, 3); + char *p2 = str2; + dfsan_set_label(j_label, &p2, sizeof(p2)); + strd = strncpy(p2, str1, 3); assert(strd == str2); assert(strncmp(str1, str2, 3) == 0); - ASSERT_ZERO_LABEL(strd); + ASSERT_LABEL(strd, j_label); + ASSERT_EQ_ORIGIN(strd, p2); + // When -dfsan-combine-pointer-labels-on-load is on, strd's label propagates + // to strd[i]'s label. When ORIGIN_TRACKING is defined, + // -dfsan-combine-pointer-labels-on-load is always off, otherwise the flag + // is on by default. +#if defined(ORIGIN_TRACKING) ASSERT_ZERO_LABEL(strd[0]); ASSERT_ZERO_LABEL(strd[1]); ASSERT_ZERO_LABEL(strd[2]); +#else + ASSERT_LABEL(strd[0], j_label); + ASSERT_LABEL(strd[1], j_label); + ASSERT_LABEL(strd[2], j_label); +#endif } -#endif // !defined(ORIGIN_TRACKING) void test_strncmp() { char str1[] = "str1", str2[] = "str2"; @@ -523,7 +586,6 @@ #endif } -#if !defined(ORIGIN_TRACKING) void test_calloc() { // With any luck this sequence of calls will cause calloc to return the same // pointer both times. This is probably the best we can do to test this @@ -538,6 +600,7 @@ free(crv); } +#if !defined(ORIGIN_TRACKING) void test_recvmmsg() { int sockfds[2]; int ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, sockfds); @@ -630,12 +693,14 @@ close(sockfds[0]); close(sockfds[1]); } +#endif // !defined(ORIGIN_TRACKING) void test_read() { char buf[16]; dfsan_set_label(i_label, buf, 1); dfsan_set_label(j_label, buf + 15, 1); + DEFINE_AND_SAVE_ORIGINS(buf) ASSERT_LABEL(buf[0], i_label); ASSERT_LABEL(buf[15], j_label); @@ -645,6 +710,7 @@ ASSERT_ZERO_LABEL(rv); ASSERT_ZERO_LABEL(buf[0]); ASSERT_ZERO_LABEL(buf[15]); + ASSERT_SAVED_ORIGINS(buf) close(fd); } @@ -653,6 +719,7 @@ dfsan_set_label(i_label, buf, 1); dfsan_set_label(j_label, buf + 15, 1); + DEFINE_AND_SAVE_ORIGINS(buf) ASSERT_LABEL(buf[0], i_label); ASSERT_LABEL(buf[15], j_label); @@ -662,6 +729,7 @@ ASSERT_ZERO_LABEL(rv); ASSERT_ZERO_LABEL(buf[0]); ASSERT_ZERO_LABEL(buf[15]); + ASSERT_SAVED_ORIGINS(buf) close(fd); } @@ -678,12 +746,15 @@ void test_clock_gettime() { struct timespec tp; dfsan_set_label(j_label, ((char *)&tp) + 3, 1); + dfsan_origin origin = dfsan_get_origin((long)(((char *)&tp)[3])); int t = clock_gettime(CLOCK_REALTIME, &tp); assert(t == 0); ASSERT_ZERO_LABEL(t); ASSERT_ZERO_LABEL(((char *)&tp)[3]); + ASSERT_ORIGIN(((char *)&tp)[3], origin); } +#if !defined(ORIGIN_TRACKING) void test_ctime_r() { char *buf = (char*) malloc(64); time_t t = 0; @@ -704,6 +775,7 @@ ASSERT_LABEL(ret, j_label); ASSERT_READ_ZERO_LABEL(buf, strlen(buf) + 1); } +#endif // !defined(ORIGIN_TRACKING) static int write_callback_count = 0; static int last_fd; @@ -728,6 +800,8 @@ write_callback_count = 0; + DEFINE_AND_SAVE_ORIGINS(buf) + // Callback should be invoked on every call to write(). int res = write(fd, buf, buf_len); assert(write_callback_count == 1); @@ -736,12 +810,21 @@ ASSERT_READ_ZERO_LABEL(last_buf, sizeof(last_buf)); ASSERT_READ_ZERO_LABEL(&last_count, sizeof(last_count)); + for (int i = 0; i < buf_len; ++i) + ASSERT_ORIGIN(last_buf[i], buf_o[i]); + + ASSERT_ZERO_ORIGINS(&last_count, sizeof(last_count)); + // Add a label to write() arguments. Check that the labels are readable from // the values passed to the callback. dfsan_set_label(i_label, &fd, sizeof(fd)); dfsan_set_label(j_label, &(buf[3]), 1); dfsan_set_label(k_label, &buf_len, sizeof(buf_len)); + dfsan_origin fd_o = dfsan_get_origin((long)fd); + dfsan_origin buf3_o = dfsan_get_origin((long)(buf[3])); + dfsan_origin buf_len_o = dfsan_get_origin((long)buf_len); + res = write(fd, buf, buf_len); assert(write_callback_count == 2); ASSERT_READ_ZERO_LABEL(&res, sizeof(res)); @@ -749,10 +832,27 @@ ASSERT_READ_LABEL(&last_buf[3], sizeof(last_buf[3]), j_label); ASSERT_READ_LABEL(last_buf, sizeof(last_buf), j_label); ASSERT_READ_LABEL(&last_count, sizeof(last_count), k_label); + ASSERT_ZERO_ORIGINS(&res, sizeof(res)); + ASSERT_INIT_ORIGINS(&last_fd, sizeof(last_fd), fd_o); + ASSERT_INIT_ORIGINS(&last_buf[3], sizeof(last_buf[3]), buf3_o); + + // Origins are assigned for every 4 contiguous 4-aligned bytes. After + // appending src to dst, origins of src can overwrite origins of dst if their + // application adddresses are within an aligned range. Other origins are not + // changed. + for (int i = 0; i < buf_len; ++i) { + size_t i_addr = size_t(&last_buf[i]); + if (((size_t(&last_buf[3]) & ~3UL) > i_addr) || + (((size_t(&last_buf[3]) + 4) & ~3UL) <= i_addr)) + ASSERT_ORIGIN(last_buf[i], buf_o[i]); + } + + ASSERT_INIT_ORIGINS(&last_count, sizeof(last_count), buf_len_o); dfsan_set_write_callback(NULL); } +#if !defined(ORIGIN_TRACKING) void test_fgets() { char *buf = (char*) malloc(128); FILE *f = fopen("/etc/passwd", "r"); @@ -1126,7 +1226,6 @@ // check-wrappers script. void test_pthread_join() {} -#if !defined(ORIGIN_TRACKING) int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size, void *data) { assert(data == (void *)3); @@ -1151,11 +1250,16 @@ size_t sizep = 0, alignp = 0; dfsan_set_label(i_label, &sizep, sizeof(sizep)); dfsan_set_label(i_label, &alignp, sizeof(alignp)); + dfsan_origin sizep_o = dfsan_get_origin(sizep); + dfsan_origin alignp_o = dfsan_get_origin(alignp); _dl_get_tls_static_info(&sizep, &alignp); ASSERT_ZERO_LABEL(sizep); ASSERT_ZERO_LABEL(alignp); + ASSERT_ORIGIN(sizep, sizep_o); + ASSERT_ORIGIN(alignp, alignp_o); } +#if !defined(ORIGIN_TRACKING) void test_strrchr() { char str1[] = "str1str1"; dfsan_set_label(i_label, &str1[7], 1); @@ -1559,17 +1663,17 @@ assert(i_j_label != j_label); assert(i_j_label != k_label); -#if !defined(ORIGIN_TRACKING) test__dl_get_tls_static_info(); -#endif // !defined(ORIGIN_TRACKING) test_bcmp(); -#if !defined(ORIGIN_TRACKING) test_calloc(); test_clock_gettime(); +#if !defined(ORIGIN_TRACKING) test_ctime_r(); +#endif // !defined(ORIGIN_TRACKING) test_dfsan_set_write_callback(); test_dl_iterate_phdr(); test_dlopen(); +#if !defined(ORIGIN_TRACKING) test_epoll_wait(); test_fgets(); #endif // !defined(ORIGIN_TRACKING) @@ -1591,18 +1695,18 @@ test_memchr(); #endif // !defined(ORIGIN_TRACKING) test_memcmp(); -#if !defined(ORIGIN_TRACKING) test_memcpy(); test_memmove(); test_memset(); +#if !defined(ORIGIN_TRACKING) test_nanosleep(); test_poll(); - test_pread(); #endif // !defined(ORIGIN_TRACKING) + test_pread(); test_pthread_create(); test_pthread_join(); -#if !defined(ORIGIN_TRACKING) test_read(); +#if !defined(ORIGIN_TRACKING) test_recvmmsg(); test_recvmsg(); test_sched_getaffinity(); @@ -1621,11 +1725,11 @@ test_strcasecmp(); test_strchr(); test_strcmp(); -#if !defined(ORIGIN_TRACKING) test_strcat(); +#if !defined(ORIGIN_TRACKING) test_strcpy(); - test_strdup(); #endif // !defined(ORIGIN_TRACKING) + test_strdup(); test_strlen(); test_strncasecmp(); test_strncmp();