1272343Sngie/*- 2272343Sngie * Copyright (c) 2013 The NetBSD Foundation, Inc. 3272343Sngie * All rights reserved. 4272343Sngie * 5272343Sngie * Redistribution and use in source and binary forms, with or without 6272343Sngie * modification, are permitted provided that the following conditions 7272343Sngie * are met: 8272343Sngie * 1. Redistributions of source code must retain the above copyright 9272343Sngie * notice, this list of conditions and the following disclaimer. 10272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 11272343Sngie * notice, this list of conditions and the following disclaimer in the 12272343Sngie * documentation and/or other materials provided with the distribution. 13272343Sngie * 14272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 15272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 16272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17272343Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 18272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24272343Sngie * POSSIBILITY OF SUCH DAMAGE. 25272343Sngie */ 26272343Sngie 27272343Sngie#include <sys/cdefs.h> 28272343Sngie__COPYRIGHT("@(#) Copyright (c) 2013\ 29272343Sngie The NetBSD Foundation, inc. All rights reserved."); 30272343Sngie__RCSID("$NetBSD: t_kauth_pr_47598.c,v 1.3 2014/04/28 08:34:16 martin Exp $"); 31272343Sngie 32272343Sngie#include <errno.h> 33272343Sngie#include <unistd.h> 34272343Sngie#include <stdio.h> 35272343Sngie#include <stdlib.h> 36272343Sngie#include <sys/sysctl.h> 37272343Sngie#include <sys/socket.h> 38272343Sngie#include <netinet/in.h> 39272343Sngie#include <arpa/inet.h> 40272343Sngie#include <atf-c.h> 41272343Sngie 42272343Sngie/* 43272343Sngie * helper function 44272343Sngie */ 45272343Sngiestatic const char curtain_name[] = "security.models.bsd44.curtain"; 46272343Sngiestatic const char securelevel_name[] = "security.models.bsd44.securelevel"; 47272343Sngie 48272343Sngiestatic bool may_lower_curtain(void); 49272343Sngiestatic int get_curtain(void); 50272343Sngiestatic void set_curtain(int newval); 51272343Sngie 52272343Sngiestatic bool 53272343Sngiemay_lower_curtain(void) 54272343Sngie{ 55272343Sngie int seclevel; 56272343Sngie size_t len = sizeof(seclevel); 57272343Sngie 58272343Sngie if (sysctlbyname(securelevel_name, &seclevel, &len, NULL, 0) != 0) 59272343Sngie atf_tc_fail("failed to read %s", securelevel_name); 60272343Sngie 61272343Sngie return seclevel <= 0; 62272343Sngie} 63272343Sngie 64272343Sngiestatic int 65272343Sngieget_curtain(void) 66272343Sngie{ 67272343Sngie int curtain; 68272343Sngie size_t len = sizeof(curtain); 69272343Sngie 70272343Sngie if (sysctlbyname(curtain_name, &curtain, &len, NULL, 0) != 0) 71272343Sngie atf_tc_fail("failed to read %s", curtain_name); 72272343Sngie 73272343Sngie return curtain; 74272343Sngie} 75272343Sngie 76272343Sngiestatic void 77272343Sngieset_curtain(int newval) 78272343Sngie{ 79272343Sngie 80272343Sngie if (sysctlbyname(curtain_name, NULL, 0, &newval, sizeof(newval)) != 0) 81272343Sngie atf_tc_fail("failed to set %s to %d", curtain_name, newval); 82272343Sngie} 83272343Sngie 84272343Sngie/* 85272343Sngie * PR kern/47598: if security.models.extensions.curtain = 1 we crash when 86272343Sngie * doing a netstat while an embryonic (not yet fully accepted) connection 87272343Sngie * exists. 88272343Sngie * This has been fixed with rev. 1.5 of 89272343Sngie * src/sys/secmodel/extensions/secmodel_extensions.c. 90272343Sngie */ 91272343Sngie 92272343Sngie 93272343SngieATF_TC(kauth_curtain); 94272343SngieATF_TC_HEAD(kauth_curtain, tc) 95272343Sngie{ 96272343Sngie atf_tc_set_md_var(tc, "require.user", "root"); 97272343Sngie atf_tc_set_md_var(tc, "require.progs", "netstat"); 98272343Sngie atf_tc_set_md_var(tc, "descr", 99272343Sngie "Checks for kernel crash with curtain active (PR kern/47598)"); 100272343Sngie} 101272343Sngie 102272343SngieATF_TC_BODY(kauth_curtain, tc) 103272343Sngie{ 104272343Sngie 105272343Sngie int old_curtain, s, s2, err; 106272343Sngie socklen_t slen; 107272343Sngie struct sockaddr_in sa; 108272343Sngie 109272343Sngie /* 110272343Sngie * save old value of "curtain" and enable it 111272343Sngie */ 112272343Sngie old_curtain = get_curtain(); 113272343Sngie if (old_curtain < 1 && !may_lower_curtain()) 114272343Sngie atf_tc_skip("curtain is not enabled and we would not be able" 115272343Sngie " to drop it later due to securelevel settings"); 116272343Sngie 117272343Sngie set_curtain(1); 118272343Sngie 119272343Sngie /* 120272343Sngie * create a socket and bind it to some arbitray free port 121272343Sngie */ 122272343Sngie s = socket(PF_INET, SOCK_STREAM|SOCK_NONBLOCK, 0); 123272343Sngie ATF_REQUIRE(s != -1); 124272343Sngie memset(&sa, 0, sizeof(sa)); 125272343Sngie sa.sin_family = AF_INET; 126272343Sngie sa.sin_len = sizeof(sa); 127272343Sngie sa.sin_addr.s_addr = inet_addr("127.0.0.1"); 128272343Sngie ATF_REQUIRE(bind(s, (struct sockaddr *)&sa, sizeof(sa))==0); 129272343Sngie ATF_REQUIRE(listen(s, 16)==0); 130272343Sngie 131272343Sngie /* 132272343Sngie * extract address and open a connection to the port 133272343Sngie */ 134272343Sngie slen = sizeof(sa); 135272343Sngie ATF_REQUIRE(getsockname(s, (struct sockaddr *)&sa, &slen)==0); 136272343Sngie s2 = socket(PF_INET, SOCK_STREAM|SOCK_NONBLOCK, 0); 137272343Sngie ATF_REQUIRE(s2 != -1); 138272343Sngie printf("port is %d\n", ntohs(sa.sin_port)); 139272343Sngie err = connect(s2, (struct sockaddr *)&sa, sizeof(sa)); 140272343Sngie ATF_REQUIRE_MSG(err == -1 && errno == EINPROGRESS, 141272343Sngie "conect returned %d with errno %d", err, errno); 142272343Sngie fflush(stdout); 143272343Sngie fflush(stderr); 144272343Sngie 145272343Sngie /* 146272343Sngie * we now have a pending, not yet accepted connection - run netstat 147272343Sngie */ 148272343Sngie system("netstat -aA"); 149272343Sngie 150272343Sngie /* 151272343Sngie * cleanup 152272343Sngie */ 153272343Sngie close(s2); 154272343Sngie close(s); 155272343Sngie 156272343Sngie /* 157272343Sngie * restore old value of curtain 158272343Sngie */ 159272343Sngie set_curtain(old_curtain); 160272343Sngie} 161272343Sngie 162272343SngieATF_TP_ADD_TCS(tp) 163272343Sngie{ 164272343Sngie ATF_TP_ADD_TC(tp, kauth_curtain); 165272343Sngie 166272343Sngie return atf_no_error(); 167272343Sngie} 168272343Sngie 169272343Sngie 170