18ce99bb4SJohn Baldwin /*-
28ce99bb4SJohn Baldwin * Copyright (c) 2018 John Baldwin <jhb@FreeBSD.org>
38ce99bb4SJohn Baldwin *
48ce99bb4SJohn Baldwin * Redistribution and use in source and binary forms, with or without
58ce99bb4SJohn Baldwin * modification, are permitted provided that the following conditions
68ce99bb4SJohn Baldwin * are met:
78ce99bb4SJohn Baldwin * 1. Redistributions of source code must retain the above copyright
88ce99bb4SJohn Baldwin * notice, this list of conditions and the following disclaimer.
98ce99bb4SJohn Baldwin * 2. Redistributions in binary form must reproduce the above copyright
108ce99bb4SJohn Baldwin * notice, this list of conditions and the following disclaimer in the
118ce99bb4SJohn Baldwin * documentation and/or other materials provided with the distribution.
128ce99bb4SJohn Baldwin *
138ce99bb4SJohn Baldwin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
148ce99bb4SJohn Baldwin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158ce99bb4SJohn Baldwin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
168ce99bb4SJohn Baldwin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
178ce99bb4SJohn Baldwin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
188ce99bb4SJohn Baldwin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
198ce99bb4SJohn Baldwin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
208ce99bb4SJohn Baldwin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
218ce99bb4SJohn Baldwin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
228ce99bb4SJohn Baldwin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
238ce99bb4SJohn Baldwin * SUCH DAMAGE.
248ce99bb4SJohn Baldwin */
258ce99bb4SJohn Baldwin
268ce99bb4SJohn Baldwin #include <sys/capsicum.h>
278ce99bb4SJohn Baldwin #include <sys/filio.h>
288ce99bb4SJohn Baldwin #include <sys/socket.h>
298ce99bb4SJohn Baldwin #include <sys/wait.h>
308ce99bb4SJohn Baldwin #include <netinet/in.h>
318ce99bb4SJohn Baldwin #include <stdio.h>
328ce99bb4SJohn Baldwin #include <stdlib.h>
338ce99bb4SJohn Baldwin #include <unistd.h>
348ce99bb4SJohn Baldwin
358ce99bb4SJohn Baldwin #include <atf-c.h>
368ce99bb4SJohn Baldwin
37*08e5c473SOlivier Cochard #include "freebsd_test_suite/macros.h"
38*08e5c473SOlivier Cochard
398ce99bb4SJohn Baldwin /*
408ce99bb4SJohn Baldwin * A variant of ATF_REQUIRE that is suitable for use in child
418ce99bb4SJohn Baldwin * processes. This only works if the parent process is tripped up by
428ce99bb4SJohn Baldwin * the early exit and fails some requirement itself.
438ce99bb4SJohn Baldwin */
448ce99bb4SJohn Baldwin #define CHILD_REQUIRE(exp) do { \
458ce99bb4SJohn Baldwin if (!(exp)) \
468ce99bb4SJohn Baldwin child_fail_require(__FILE__, __LINE__, \
478ce99bb4SJohn Baldwin #exp " not met"); \
488ce99bb4SJohn Baldwin } while (0)
498ce99bb4SJohn Baldwin
508ce99bb4SJohn Baldwin static __dead2 void
child_fail_require(const char * file,int line,const char * str)518ce99bb4SJohn Baldwin child_fail_require(const char *file, int line, const char *str)
528ce99bb4SJohn Baldwin {
538ce99bb4SJohn Baldwin char buf[128];
548ce99bb4SJohn Baldwin
558ce99bb4SJohn Baldwin snprintf(buf, sizeof(buf), "%s:%d: %s\n", file, line, str);
568ce99bb4SJohn Baldwin write(2, buf, strlen(buf));
578ce99bb4SJohn Baldwin _exit(32);
588ce99bb4SJohn Baldwin }
598ce99bb4SJohn Baldwin
608ce99bb4SJohn Baldwin /*
618ce99bb4SJohn Baldwin * Exercise the edge case of a custom ioctl list being copied from a
628ce99bb4SJohn Baldwin * listen socket to an accepted socket.
638ce99bb4SJohn Baldwin */
648ce99bb4SJohn Baldwin ATF_TC_WITHOUT_HEAD(cap_ioctls__listen_copy);
ATF_TC_BODY(cap_ioctls__listen_copy,tc)658ce99bb4SJohn Baldwin ATF_TC_BODY(cap_ioctls__listen_copy, tc)
668ce99bb4SJohn Baldwin {
678ce99bb4SJohn Baldwin struct sockaddr_in sin;
688ce99bb4SJohn Baldwin cap_rights_t rights;
698ce99bb4SJohn Baldwin u_long cmds[] = { FIONREAD };
708ce99bb4SJohn Baldwin socklen_t len;
718ce99bb4SJohn Baldwin pid_t pid;
728ce99bb4SJohn Baldwin char dummy;
738ce99bb4SJohn Baldwin int s[2], status;
748ce99bb4SJohn Baldwin
75*08e5c473SOlivier Cochard ATF_REQUIRE_FEATURE("security_capabilities");
76*08e5c473SOlivier Cochard
778ce99bb4SJohn Baldwin s[0] = socket(AF_INET, SOCK_STREAM, 0);
788ce99bb4SJohn Baldwin ATF_REQUIRE(s[0] > 0);
798ce99bb4SJohn Baldwin
808ce99bb4SJohn Baldwin /* Bind to an arbitrary unused port. */
818ce99bb4SJohn Baldwin memset(&sin, 0, sizeof(sin));
828ce99bb4SJohn Baldwin sin.sin_len = sizeof(sin);
838ce99bb4SJohn Baldwin sin.sin_family = AF_INET;
848ce99bb4SJohn Baldwin sin.sin_port = 0;
858ce99bb4SJohn Baldwin sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
868ce99bb4SJohn Baldwin ATF_REQUIRE(bind(s[0], (struct sockaddr *)&sin, sizeof(sin)) == 0);
878ce99bb4SJohn Baldwin
888ce99bb4SJohn Baldwin CHILD_REQUIRE(listen(s[0], 1) == 0);
898ce99bb4SJohn Baldwin
908ce99bb4SJohn Baldwin len = sizeof(sin);
918ce99bb4SJohn Baldwin ATF_REQUIRE(getsockname(s[0], (struct sockaddr *)&sin, &len) == 0);
928ce99bb4SJohn Baldwin ATF_REQUIRE(len == sizeof(sin));
938ce99bb4SJohn Baldwin
948ce99bb4SJohn Baldwin cap_rights_init(&rights, CAP_ACCEPT, CAP_IOCTL);
958ce99bb4SJohn Baldwin ATF_REQUIRE(cap_rights_limit(s[0], &rights) == 0);
968ce99bb4SJohn Baldwin ATF_REQUIRE(cap_ioctls_limit(s[0], cmds, nitems(cmds)) == 0);
978ce99bb4SJohn Baldwin
988ce99bb4SJohn Baldwin pid = fork();
998ce99bb4SJohn Baldwin if (pid == 0) {
1008ce99bb4SJohn Baldwin s[1] = accept(s[0], NULL, NULL);
1018ce99bb4SJohn Baldwin CHILD_REQUIRE(s[1] > 0);
1028ce99bb4SJohn Baldwin
1038ce99bb4SJohn Baldwin /* Close both sockets during exit(). */
1048ce99bb4SJohn Baldwin exit(0);
1058ce99bb4SJohn Baldwin }
1068ce99bb4SJohn Baldwin
1078ce99bb4SJohn Baldwin ATF_REQUIRE(pid > 0);
1088ce99bb4SJohn Baldwin
1098ce99bb4SJohn Baldwin ATF_REQUIRE(close(s[0]) == 0);
1108ce99bb4SJohn Baldwin s[1] = socket(AF_INET, SOCK_STREAM, 0);
1118ce99bb4SJohn Baldwin ATF_REQUIRE(s[1] > 0);
1128ce99bb4SJohn Baldwin ATF_REQUIRE(connect(s[1], (struct sockaddr *)&sin, sizeof(sin)) == 0);
1138ce99bb4SJohn Baldwin ATF_REQUIRE(read(s[1], &dummy, sizeof(dummy)) == 0);
1148ce99bb4SJohn Baldwin ATF_REQUIRE(close(s[1]) == 0);
1158ce99bb4SJohn Baldwin
1168ce99bb4SJohn Baldwin ATF_REQUIRE(wait(&status) == pid);
1178ce99bb4SJohn Baldwin ATF_REQUIRE(WIFEXITED(status));
1188ce99bb4SJohn Baldwin ATF_REQUIRE(WEXITSTATUS(status) == 0);
1198ce99bb4SJohn Baldwin }
1208ce99bb4SJohn Baldwin
ATF_TP_ADD_TCS(tp)1218ce99bb4SJohn Baldwin ATF_TP_ADD_TCS(tp)
1228ce99bb4SJohn Baldwin {
1238ce99bb4SJohn Baldwin
1248ce99bb4SJohn Baldwin ATF_TP_ADD_TC(tp, cap_ioctls__listen_copy);
1258ce99bb4SJohn Baldwin
1268ce99bb4SJohn Baldwin return (atf_no_error());
1278ce99bb4SJohn Baldwin }
128