From: Dmitry V. Levin Date: Wed, 19 Aug 2015 01:25:39 +0000 (+0000) Subject: tests: add sendfile.test and sendfile64.test X-Git-Tag: v4.11~266 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=49182851eb84cc1606efcfa5a6127cfa4f03915b;p=strace tests: add sendfile.test and sendfile64.test * tests/sendfile.c: New file. * tests/sendfile64.c: New file. * tests/sendfile.test: New test. * tests/sendfile64.test: New test. * tests/Makefile.am (check_PROGRAMS): Add sendfile and sendfile64. (TESTS): Add sendfile.test and sendfile64.test. * tests/.gitignore: Add sendfile and sendfile64. --- diff --git a/tests/.gitignore b/tests/.gitignore index 9cf3d9b6..b272ceb7 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -30,6 +30,8 @@ sched_xetattr scm_rights seccomp select +sendfile +sendfile64 set_ptracer_any sigaction sigaltstack diff --git a/tests/Makefile.am b/tests/Makefile.am index 45e3ded0..0876a46f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -41,6 +41,8 @@ check_PROGRAMS = \ scm_rights \ seccomp \ select \ + sendfile \ + sendfile64 \ set_ptracer_any \ sigaction \ sigaltstack \ @@ -98,6 +100,8 @@ TESTS = \ scm_rights-fd.test \ seccomp.test \ select.test \ + sendfile.test \ + sendfile64.test \ sigaction.test \ sigaltstack.test \ signalfd.test \ diff --git a/tests/sendfile.c b/tests/sendfile.c new file mode 100644 index 00000000..6f71a5b0 --- /dev/null +++ b/tests/sendfile.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2015 Dmitry V. Levin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __NR_sendfile + +int +main(int ac, const char **av) +{ + assert(ac == 2); + + (void) close(0); + if (open("/dev/zero", O_RDONLY) != 0) + return 77; + + int sv[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv)) + return 77; + + int reg_in = open(av[1], O_RDONLY); + if (reg_in < 0) + return 77; + + struct stat stb; + if (fstat(reg_in, &stb)) + return 77; + const size_t blen = stb.st_size / 3; + const size_t alen = stb.st_size - blen; + assert(S_ISREG(stb.st_mode) && blen > 0); + + const size_t page_len = sysconf(_SC_PAGESIZE); + if (!syscall(__NR_sendfile, 0, 1, NULL, page_len) || + EBADF != errno) + return 77; + printf("sendfile\\(0, 1, NULL, %lu\\) += -1 EBADF .*\n", + (unsigned long) page_len); + + void *p = mmap(NULL, page_len * 2, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (MAP_FAILED == p || munmap(p + page_len, page_len)) + return 77; + + if (!syscall(__NR_sendfile, 0, 1, p + page_len, page_len)) + return 77; + printf("sendfile\\(0, 1, %#lx, %lu\\) += -1 EFAULT .*\n", + (unsigned long) p + page_len, (unsigned long) page_len); + + if (syscall(__NR_sendfile, sv[1], reg_in, NULL, alen) != (long) alen) + return 77; + printf("sendfile\\(%d, %d, NULL, %lu\\) += %lu\n", + sv[1], reg_in, (unsigned long) alen, + (unsigned long) alen); + + uint32_t *p_off = p + page_len - sizeof(uint32_t); + if (syscall(__NR_sendfile, sv[1], reg_in, p_off, alen) != (long) alen) { + printf("sendfile\\(%d, %d, %#lx, %lu\\) += -1 EFAULT .*\n", + sv[1], reg_in, (unsigned long) p_off, + (unsigned long) alen); + --p_off; + if (syscall(__NR_sendfile, sv[1], reg_in, p_off, alen) + != (long) alen) + return 77; + } + printf("sendfile\\(%d, %d, \\[0\\] => \\[%lu\\], %lu\\) += %lu\n", + sv[1], reg_in, (unsigned long) alen, + (unsigned long) alen, (unsigned long) alen); + + if (syscall(__NR_sendfile, sv[1], reg_in, p_off, stb.st_size + 1) + != (long) blen) + return 77; + printf("sendfile\\(%d, %d, \\[%lu\\] => \\[%lu\\], %lu\\) += %lu\n", + sv[1], reg_in, (unsigned long) alen, + (unsigned long) stb.st_size, + (unsigned long) stb.st_size + 1, + (unsigned long) blen); + + if (p_off == p + page_len - sizeof(uint64_t)) { + uint64_t *p_off64 = (uint64_t *) p_off; + *p_off64 = 0xcafef00dfacefeed; + if (!syscall(__NR_sendfile, sv[1], reg_in, p_off64, 1)) + return 77; + printf("sendfile\\(%d, %d, \\[14627392582579060461\\], 1\\) += -1 EINVAL .*\n", + sv[1], reg_in); + *p_off64 = 0xdefaced; + } else { + *p_off = 0xdefaced; + } + if (syscall(__NR_sendfile, sv[1], reg_in, p_off, 1)) + return 77; + printf("sendfile\\(%d, %d, \\[233811181\\], 1\\) += 0\n", + sv[1], reg_in); + + return 0; +} + +#else + +int +main(void) +{ + return 77; +} + +#endif diff --git a/tests/sendfile.test b/tests/sendfile.test new file mode 100755 index 00000000..23aacac7 --- /dev/null +++ b/tests/sendfile.test @@ -0,0 +1,14 @@ +#!/bin/sh + +# Check sendfile syscall decoding. + +. "${srcdir=.}/init.sh" + +exe="./${ME_%.test}" +run_prog "$exe" "$exe" > /dev/null +OUT="$LOG.out" +run_strace -esendfile $args > "$OUT" +match_grep "$LOG" "$OUT" +rm -f "$OUT" + +exit 0 diff --git a/tests/sendfile64.c b/tests/sendfile64.c new file mode 100644 index 00000000..d52fbadb --- /dev/null +++ b/tests/sendfile64.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2015 Dmitry V. Levin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __NR_sendfile64 + +int +main(int ac, const char **av) +{ + assert(ac == 2); + + (void) close(0); + if (open("/dev/zero", O_RDONLY) != 0) + return 77; + + int sv[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv)) + return 77; + + int reg_in = open(av[1], O_RDONLY); + if (reg_in < 0) + return 77; + + struct stat stb; + if (fstat(reg_in, &stb)) + return 77; + const size_t blen = stb.st_size / 3; + const size_t alen = stb.st_size - blen; + assert(S_ISREG(stb.st_mode) && blen > 0); + + const size_t page_len = sysconf(_SC_PAGESIZE); + if (!syscall(__NR_sendfile64, 0, 1, NULL, page_len) || + EBADF != errno) + return 77; + printf("sendfile64\\(0, 1, NULL, %lu\\) += -1 EBADF .*\n", + (unsigned long) page_len); + + void *p = mmap(NULL, page_len * 2, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (MAP_FAILED == p || munmap(p + page_len, page_len)) + return 77; + + if (!syscall(__NR_sendfile64, 0, 1, p + page_len, page_len)) + return 77; + printf("sendfile64\\(0, 1, %#lx, %lu\\) += -1 EFAULT .*\n", + (unsigned long) p + page_len, (unsigned long) page_len); + + if (syscall(__NR_sendfile64, sv[1], reg_in, NULL, alen) != (long) alen) + return 77; + printf("sendfile64\\(%d, %d, NULL, %lu\\) += %lu\n", + sv[1], reg_in, (unsigned long) alen, + (unsigned long) alen); + + uint64_t *p_off = p + page_len - sizeof(uint64_t); + if (syscall(__NR_sendfile64, sv[1], reg_in, p_off, alen) != (long) alen) + return 77; + printf("sendfile64\\(%d, %d, \\[0\\] => \\[%lu\\], %lu\\) += %lu\n", + sv[1], reg_in, (unsigned long) alen, + (unsigned long) alen, (unsigned long) alen); + + if (syscall(__NR_sendfile64, sv[1], reg_in, p_off, stb.st_size + 1) + != (long) blen) + return 77; + printf("sendfile64\\(%d, %d, \\[%lu\\] => \\[%lu\\], %lu\\) += %lu\n", + sv[1], reg_in, (unsigned long) alen, + (unsigned long) stb.st_size, + (unsigned long) stb.st_size + 1, + (unsigned long) blen); + + *p_off = 0xcafef00dfacefeed; + if (!syscall(__NR_sendfile64, sv[1], reg_in, p_off, 1)) + return 77; + printf("sendfile64\\(%d, %d, \\[14627392582579060461\\], 1\\) += -1 EINVAL .*\n", + sv[1], reg_in); + + *p_off = 0xfacefeed; + if (syscall(__NR_sendfile64, sv[1], reg_in, p_off, 1)) + return 77; + printf("sendfile64\\(%d, %d, \\[4207869677\\], 1\\) += 0\n", + sv[1], reg_in); + + return 0; +} + +#else + +int +main(void) +{ + return 77; +} + +#endif diff --git a/tests/sendfile64.test b/tests/sendfile64.test new file mode 100755 index 00000000..a50bb885 --- /dev/null +++ b/tests/sendfile64.test @@ -0,0 +1,14 @@ +#!/bin/sh + +# Check sendfile64 syscall decoding. + +. "${srcdir=.}/init.sh" + +exe="./${ME_%.test}" +run_prog "$exe" "$exe" > /dev/null +OUT="$LOG.out" +run_strace -esendfile64 $args > "$OUT" +match_grep "$LOG" "$OUT" +rm -f "$OUT" + +exit 0