Path: blob/main/tests/sys/capsicum/bindat_connectat.c
39482 views
/*1* Copyright (c) 2017 Jan Kokemüller2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6* 1. Redistributions of source code must retain the above copyright7* notice, this list of conditions and the following disclaimer.8* 2. Redistributions in binary form must reproduce the above copyright9* notice, this list of conditions and the following disclaimer in the10* documentation and/or other materials provided with the distribution.11*12* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND13* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE14* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE15* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE16* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL17* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS18* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)19* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT20* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY21* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF22* SUCH DAMAGE.23*/2425#include <sys/param.h>26#include <sys/capsicum.h>27#include <sys/socket.h>28#include <sys/sysctl.h>29#include <sys/stat.h>3031#include <netinet/in.h>32#include <arpa/inet.h>3334#include <atf-c.h>35#include <dlfcn.h>36#include <errno.h>37#include <stdarg.h>38#include <stdlib.h>39#include <string.h>4041#include "freebsd_test_suite/macros.h"4243static int rootfd = -1;4445/* circumvent bug 215690 */46int47open(const char *path, int flags, ...)48{49mode_t mode = 0;5051if (flags & O_CREAT) {52va_list ap;53va_start(ap, flags);54mode = (mode_t) va_arg(ap, int);55va_end(ap);56}5758if (path && path[0] == '/' && rootfd >= 0) {59return (openat(rootfd, path + 1, flags, mode));60} else {61return (openat(AT_FDCWD, path, flags, mode));62}63}6465static void66check_capsicum(void)67{68ATF_REQUIRE_FEATURE("security_capabilities");69ATF_REQUIRE_FEATURE("security_capability_mode");7071ATF_REQUIRE((rootfd = open("/", O_EXEC | O_CLOEXEC)) >= 0);72}7374typedef int (*socket_fun)(int, const struct sockaddr *, socklen_t);7576static int77connectat_fdcwd(int s, const struct sockaddr *name, socklen_t namelen)78{7980return (connectat(AT_FDCWD, s, name, namelen));81}8283static int84bindat_fdcwd(int s, const struct sockaddr *name, socklen_t namelen)85{8687return (bindat(AT_FDCWD, s, name, namelen));88}899091ATF_TC(bindat_connectat_1);92ATF_TC_HEAD(bindat_connectat_1, tc)93{94atf_tc_set_md_var(tc, "descr",95"Verify that connect/bind work in normal case");96}9798static void99check_1(socket_fun f, int s, const struct sockaddr_in *name)100{101102ATF_REQUIRE((s = socket(AF_INET, SOCK_STREAM, 0)) >= 0);103ATF_REQUIRE_ERRNO(EAFNOSUPPORT,104f(s, (const struct sockaddr *)(name),105sizeof(struct sockaddr_in)) < 0);106}107108ATF_TC_BODY(bindat_connectat_1, tc)109{110struct sockaddr_in sin;111112memset(&sin, 0, sizeof(sin));113sin.sin_family = AF_INET;114sin.sin_port = htons(0);115sin.sin_addr.s_addr = htonl(0xE0000000);116117check_1(bindat_fdcwd, 0, &sin);118check_1(bind, 0, &sin);119check_1(connectat_fdcwd, 0, &sin);120check_1(connect, 0, &sin);121}122123124ATF_TC(bindat_connectat_2);125ATF_TC_HEAD(bindat_connectat_2, tc)126{127atf_tc_set_md_var(tc, "descr",128"Verify that connect/bind are disabled in cap-mode");129}130131static void132check_2(socket_fun f, int s, const struct sockaddr_in *name)133{134135ATF_REQUIRE_ERRNO(ECAPMODE,136f(s, (const struct sockaddr *)name,137sizeof(struct sockaddr_in)) < 0);138}139140ATF_TC_BODY(bindat_connectat_2, tc)141{142int sock;143struct sockaddr_in sin;144145check_capsicum();146147ATF_REQUIRE(cap_enter() >= 0);148149/* note: sock is created _after_ cap_enter() and contains all rights */150ATF_REQUIRE((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0);151152memset(&sin, 0, sizeof(sin));153sin.sin_family = AF_INET;154/* dummy port and multicast address (224.0.0.0) to distinguish two155* cases:156* - ECAPMODE/ENOTCAPABLE --> call blocked by capsicum157* - EAFNOSUPPORT --> call went through to protocol layer158*/159sin.sin_port = htons(0);160sin.sin_addr.s_addr = htonl(0xE0000000);161162check_2(bindat_fdcwd, sock, &sin);163check_2(bind, sock, &sin);164check_2(connectat_fdcwd, sock, &sin);165check_2(connect, sock, &sin);166}167168169ATF_TC(bindat_connectat_3);170ATF_TC_HEAD(bindat_connectat_3, tc)171{172atf_tc_set_md_var(tc, "descr",173"Check that taking away CAP_BIND/CAP_CONNECT "174"sabotages bind/connect");175}176177static void178check_3(socket_fun f, int s, const struct sockaddr_in *name,179cap_rights_t *rights, cap_rights_t *sub_rights)180{181182ATF_REQUIRE((s = socket(AF_INET, SOCK_STREAM, 0)) >= 0);183ATF_REQUIRE(cap_rights_limit(s, rights) >= 0);184ATF_REQUIRE_ERRNO(EAFNOSUPPORT,185f(s, (const struct sockaddr *)name,186sizeof(struct sockaddr_in)) < 0);187ATF_REQUIRE(cap_rights_limit(s,188cap_rights_remove(rights, sub_rights)) >= 0);189ATF_REQUIRE_ERRNO(ENOTCAPABLE,190f(s, (const struct sockaddr *)name,191sizeof(struct sockaddr_in)) < 0);192}193194ATF_TC_BODY(bindat_connectat_3, tc)195{196struct sockaddr_in sin;197cap_rights_t rights, sub_rights;198199check_capsicum();200201memset(&sin, 0, sizeof(sin));202sin.sin_family = AF_INET;203sin.sin_port = htons(0);204sin.sin_addr.s_addr = htonl(0xE0000000);205206check_3(bindat_fdcwd, 0, &sin,207cap_rights_init(&rights, CAP_SOCK_SERVER),208cap_rights_init(&sub_rights, CAP_BIND));209check_3(bind, 0, &sin,210cap_rights_init(&rights, CAP_SOCK_SERVER),211cap_rights_init(&sub_rights, CAP_BIND));212check_3(connectat_fdcwd, 0, &sin,213cap_rights_init(&rights, CAP_SOCK_CLIENT),214cap_rights_init(&sub_rights, CAP_CONNECT));215check_3(connect, 0, &sin,216cap_rights_init(&rights, CAP_SOCK_CLIENT),217cap_rights_init(&sub_rights, CAP_CONNECT));218}219220221ATF_TP_ADD_TCS(tp)222{223224ATF_TP_ADD_TC(tp, bindat_connectat_1);225ATF_TP_ADD_TC(tp, bindat_connectat_2);226ATF_TP_ADD_TC(tp, bindat_connectat_3);227228return (atf_no_error());229}230231232