diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc index 29fe4721ba40d..521fc116f2888 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc @@ -3205,6 +3205,28 @@ POST_SYSCALL(futex) COMMON_SYSCALL_BLOCKING_END(); } +PRE_SYSCALL(copy_file_range) +(int fdin, __sanitizer___kernel_off_t *offin, int fdout, + __sanitizer___kernel_off_t *offout, SIZE_T size, unsigned int flags) { + if (offin != nullptr) { + PRE_READ(offin, sizeof(*offin)); + } + if (offout != nullptr) { + PRE_READ(offout, sizeof(*offout)); + } +} + +POST_SYSCALL(copy_file_range) +(SSIZE_T, int fdin, __sanitizer___kernel_off_t *offin, int fdout, + __sanitizer___kernel_off_t *offout, SIZE_T size, unsigned int flags) { + if (offin != nullptr) { + POST_WRITE(offin, sizeof(*offin)); + } + if (offout != nullptr) { + POST_WRITE(offout, sizeof(*offout)); + } +} + } // extern "C" # undef PRE_SYSCALL diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/copy_file_range.c b/compiler-rt/test/sanitizer_common/TestCases/Linux/copy_file_range.c new file mode 100644 index 0000000000000..2fc6ef11cd1ee --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/copy_file_range.c @@ -0,0 +1,42 @@ +// RUN: %clangxx -O0 %s -o %t + +// REQUIRES: glibc + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif +#include +#include +#include +#include +#include + +#if !defined(__GLIBC_PREREQ) +# define __GLIBC_PREREQ(a, b) 0 +#endif + +#if !__GLIBC_PREREQ(2, 27) +# define copy_file_range(a, b, c, d, e) \ + (ssize_t) syscall(__NR_copy_file_range, a, b, c, d, e) +#endif + +int main(void) { + int fdin = open("/proc/self/maps", O_RDONLY); + assert(fdin > 0); + char tmp[] = "/tmp/map.XXXXXX"; + int fdout = mkstemp(tmp); + assert(fdout > 0); + off_t offin = -1, offout = 0; + ssize_t cpy = copy_file_range(fdin, &offin, fdout, &offout, 8, 0); + assert(cpy < 0); + offin = 0; + offout = 16; + cpy = copy_file_range(fdin, &offin, fdout, &offout, 8, 0); + assert(cpy < 0); + offout = 0; + cpy = copy_file_range(fdin, &offin, fdout, &offout, 8, 0); + assert(cpy == 8); + close(fdout); + close(fdin); + return 0; +}