From: Eugene Syromyatnikov Date: Sat, 24 Dec 2016 16:18:51 +0000 (+0300) Subject: tests: check ioctl(SIOCGIFCONF) decoding X-Git-Tag: v4.16~105 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=589e3285d5780c6e03ade8c9884f1684e68c2fd7;p=strace tests: check ioctl(SIOCGIFCONF) decoding * tests/ioctl_sock_gifconf.c: New file. * tests/ioctl_sock_gifconf.test: New test. * tests/.gitignore: Add ioctl_sock_gifconf. * tests/Makefile.am (check_PROGRAMS): Likewise. (DECODER_TESTS): Add ioctl_sock_gifconf.test. --- diff --git a/tests/.gitignore b/tests/.gitignore index 1ede2c41..a0a400a5 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -121,6 +121,7 @@ ioctl_evdev-v ioctl_mtd ioctl_rtc ioctl_rtc-v +ioctl_sock_gifconf ioctl_uffdio ioctl_v4l2 ioperm diff --git a/tests/Makefile.am b/tests/Makefile.am index bd8f3d54..d9dd1c98 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -182,6 +182,7 @@ check_PROGRAMS = \ ioctl_mtd \ ioctl_rtc \ ioctl_rtc-v \ + ioctl_sock_gifconf \ ioctl_uffdio \ ioctl_v4l2 \ ioperm \ @@ -577,6 +578,7 @@ DECODER_TESTS = \ ioctl_mtd.test \ ioctl_rtc.test \ ioctl_rtc-v.test \ + ioctl_sock_gifconf.test \ ioctl_uffdio.test \ ioctl_v4l2.test \ ioperm.test \ diff --git a/tests/ioctl_sock_gifconf.c b/tests/ioctl_sock_gifconf.c new file mode 100644 index 00000000..ae0bea4f --- /dev/null +++ b/tests/ioctl_sock_gifconf.c @@ -0,0 +1,182 @@ +/* + * Check decoding of SIOCGIFCONF command of ioctl syscall. + * + * Copyright (c) 2016 Eugene Syromyatnikov + * 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. + */ + +#include "tests.h" + +#include +#include +#include + +#include +#include +#include +#include + +#define MAX_STRLEN 1 + +static void +print_ifc_len(int val) +{ + if (val % (int) sizeof(struct ifreq)) + printf("%d", val); + else + printf("%d * sizeof(struct ifreq)", + val / (int) sizeof(struct ifreq)); +} + +static void +print_ifconf(struct ifconf *ifc, int in_len, char *in_buf, long rc) +{ + if (in_buf) { + printf("{ifc_len="); + print_ifc_len(in_len); + + if (in_len != ifc->ifc_len) { + printf(" => "); + print_ifc_len(ifc->ifc_len); + } + } else { + printf("{ifc_len="); + print_ifc_len(ifc->ifc_len); + } + + printf(", ifc_buf="); + + if ((rc < 0) || !in_buf) { + if (in_buf) + printf("%p", in_buf); + else + printf("NULL"); + } else { + int i; + + printf("["); + for (i = 0; i < (ifc->ifc_len) && + i < (int) (MAX_STRLEN * sizeof(struct ifreq)); + i += sizeof(struct ifreq)) { + struct ifreq *ifr = (struct ifreq *) (ifc->ifc_buf + i); + struct sockaddr_in *const sa_in = + (struct sockaddr_in *) &(ifr->ifr_addr); + + if (i) + printf(", "); + printf("{ifr_name=\"%s\", ifr_addr={sa_family=AF_INET, " + "sin_port=htons(%u), sin_addr=inet_addr(\"%s\")}" + "}", ifr->ifr_name, ntohs(sa_in->sin_port), + inet_ntoa(sa_in->sin_addr)); + } + + if ((size_t) (ifc->ifc_len - i) >= sizeof(struct ifreq)) + printf(", ..."); + + printf("]"); + } + + printf("}"); +} + +static void +gifconf_ioctl(int fd, struct ifconf *ifc, bool ifc_valid) +{ + const char * errstr; + int in_len; + char *in_buf; + long rc; + + if (ifc_valid) { + in_len = ifc->ifc_len; + in_buf = ifc->ifc_buf; + } + + rc = ioctl(fd, SIOCGIFCONF, ifc); + errstr = sprintrc(rc); + + printf("ioctl(%d, SIOCGIFCONF, ", fd); + if (ifc_valid) { + print_ifconf(ifc, in_len, in_buf, rc); + } else { + if (ifc) + printf("%p", ifc); + else + printf("NULL"); + } + + printf(") = %s\n", errstr); +} + +int +main(int argc, char *argv[]) +{ + struct ifreq *ifr = tail_alloc(2 * sizeof(*ifr)); + struct ifconf *ifc = tail_alloc(sizeof(*ifc)); + + struct sockaddr_in addr; + int fd; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + perror_msg_and_skip("socket AF_INET"); + + gifconf_ioctl(fd, NULL, false); + gifconf_ioctl(fd, ifc + 1, false); + + ifc->ifc_len = 3141592653U; + ifc->ifc_buf = NULL; + gifconf_ioctl(fd, ifc, true); + + ifc->ifc_len = 0; + ifc->ifc_buf = (char *) (ifr + 2); + gifconf_ioctl(fd, ifc, true); + + ifc->ifc_len = 1; + ifc->ifc_buf = (char *) (ifr + 1); + gifconf_ioctl(fd, ifc, true); + + ifc->ifc_len = 1 * sizeof(*ifr); + ifc->ifc_buf = (char *) (ifr + 1); + gifconf_ioctl(fd, ifc, true); + + ifc->ifc_len = 2 * sizeof(*ifr); + ifc->ifc_buf = (char *) (ifr + 1); + gifconf_ioctl(fd, ifc, true); + + ifc->ifc_len = 2 * sizeof(*ifr) + 2; + ifc->ifc_buf = (char *) ifr; + gifconf_ioctl(fd, ifc, true); + + ifc->ifc_len = 3 * sizeof(*ifr) + 4; + ifc->ifc_buf = (char *) ifr; + gifconf_ioctl(fd, ifc, true); + + puts("+++ exited with 0 +++"); + return 0; +} diff --git a/tests/ioctl_sock_gifconf.test b/tests/ioctl_sock_gifconf.test new file mode 100755 index 00000000..2e2fc019 --- /dev/null +++ b/tests/ioctl_sock_gifconf.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Check decoding of SIOCGIFCONF ioctl. + +. "${srcdir=.}/init.sh" + +run_prog > /dev/null +run_strace -a28 -s1 -eioctl $args > "$EXP" +check_prog grep +grep -v '^ioctl([012],' < "$LOG" > "$OUT" +match_diff "$OUT" "$EXP" +rm -f "$EXP" "$OUT"