Path: blob/main/tests/sys/vfs/lookup_cap_dotdot.c
105170 views
/*-1* Copyright (c) 2016 Ed Maste <[email protected]>2* Copyright (c) 2016 Conrad Meyer <[email protected]>3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*/2526#include <sys/param.h>27#include <sys/capsicum.h>28#include <sys/sysctl.h>29#include <sys/stat.h>3031#include <atf-c.h>32#include <errno.h>33#include <stdlib.h>34#include <string.h>3536#include "freebsd_test_suite/macros.h"3738static int dirfd = -1;39static char *abspath;4041static void42touchat(int _dirfd, const char *name)43{44int fd;4546ATF_REQUIRE((fd = openat(_dirfd, name, O_CREAT | O_TRUNC | O_WRONLY,470777)) >= 0);48ATF_REQUIRE(close(fd) == 0);49}5051static void52prepare_dotdot_tests(void)53{54char cwd[MAXPATHLEN];5556ATF_REQUIRE(getcwd(cwd, sizeof(cwd)) != NULL);57asprintf(&abspath, "%s/testdir/d1/f1", cwd);5859ATF_REQUIRE(mkdir("testdir", 0777) == 0);60ATF_REQUIRE((dirfd = open("testdir", O_RDONLY)) >= 0);6162ATF_REQUIRE(mkdirat(dirfd, "d1", 0777) == 0);63ATF_REQUIRE(mkdirat(dirfd, "d1/d2", 0777) == 0);64ATF_REQUIRE(mkdirat(dirfd, "d1/d2/d3", 0777) == 0);65touchat(dirfd, "d1/f1");66touchat(dirfd, "d1/d2/f2");67touchat(dirfd, "d1/d2/d3/f3");68ATF_REQUIRE(symlinkat("d1/d2/d3", dirfd, "l3") == 0);69ATF_REQUIRE(symlinkat("../testdir/d1", dirfd, "lup") == 0);70ATF_REQUIRE(symlinkat("../..", dirfd, "d1/d2/d3/ld1") == 0);71ATF_REQUIRE(symlinkat("../../f1", dirfd, "d1/d2/d3/lf1") == 0);72}7374static void75check_capsicum(void)76{77ATF_REQUIRE_FEATURE("security_capabilities");78ATF_REQUIRE_FEATURE("security_capability_mode");79ATF_REQUIRE_SYSCTL_BOOL("kern.trap_enotcap", false);80}8182/*83* Positive tests84*/85ATF_TC(openat__basic_positive);86ATF_TC_HEAD(openat__basic_positive, tc)87{88atf_tc_set_md_var(tc, "descr", "Basic positive openat testcases");89}9091ATF_TC_BODY(openat__basic_positive, tc)92{93prepare_dotdot_tests();9495ATF_REQUIRE(openat(dirfd, "d1/d2/d3/f3", O_RDONLY) >= 0);96ATF_REQUIRE(openat(dirfd, "d1/d2/d3/../../f1", O_RDONLY) >= 0);97ATF_REQUIRE(openat(dirfd, "l3/f3", O_RDONLY) >= 0);98ATF_REQUIRE(openat(dirfd, "l3/../../f1", O_RDONLY) >= 0);99ATF_REQUIRE(openat(dirfd, "../testdir/d1/f1", O_RDONLY) >= 0);100ATF_REQUIRE(openat(dirfd, "lup/f1", O_RDONLY) >= 0);101ATF_REQUIRE(openat(dirfd, "l3/ld1", O_RDONLY) >= 0);102ATF_REQUIRE(openat(dirfd, "l3/lf1", O_RDONLY) >= 0);103ATF_REQUIRE(open(abspath, O_RDONLY) >= 0);104ATF_REQUIRE(openat(dirfd, abspath, O_RDONLY) >= 0);105}106107ATF_TC(lookup_cap_dotdot__basic);108ATF_TC_HEAD(lookup_cap_dotdot__basic, tc)109{110atf_tc_set_md_var(tc, "descr",111"Validate cap-mode (testdir)/d1/.. lookup");112}113114ATF_TC_BODY(lookup_cap_dotdot__basic, tc)115{116cap_rights_t rights;117118check_capsicum();119prepare_dotdot_tests();120121cap_rights_init(&rights, CAP_LOOKUP, CAP_READ);122ATF_REQUIRE(cap_rights_limit(dirfd, &rights) >= 0);123124ATF_REQUIRE(cap_enter() >= 0);125126ATF_REQUIRE_MSG(openat(dirfd, "d1/..", O_RDONLY) >= 0, "%s",127strerror(errno));128}129130ATF_TC(lookup_cap_dotdot__advanced);131ATF_TC_HEAD(lookup_cap_dotdot__advanced, tc)132{133atf_tc_set_md_var(tc, "descr",134"Validate cap-mode (testdir)/d1/.. lookup");135}136137ATF_TC_BODY(lookup_cap_dotdot__advanced, tc)138{139cap_rights_t rights;140141check_capsicum();142prepare_dotdot_tests();143144cap_rights_init(&rights, CAP_LOOKUP, CAP_READ);145ATF_REQUIRE(cap_rights_limit(dirfd, &rights) >= 0);146147ATF_REQUIRE(cap_enter() >= 0);148149ATF_REQUIRE(openat(dirfd, "d1/d2/d3/../../f1", O_RDONLY) >= 0);150ATF_REQUIRE(openat(dirfd, "l3/../../f1", O_RDONLY) >= 0);151ATF_REQUIRE(openat(dirfd, "l3/ld1", O_RDONLY) >= 0);152ATF_REQUIRE(openat(dirfd, "l3/lf1", O_RDONLY) >= 0);153}154155/*156* Negative tests157*/158ATF_TC(openat__basic_negative);159ATF_TC_HEAD(openat__basic_negative, tc)160{161atf_tc_set_md_var(tc, "descr", "Basic negative openat testcases");162}163164ATF_TC_BODY(openat__basic_negative, tc)165{166prepare_dotdot_tests();167168ATF_REQUIRE_ERRNO(ENOENT,169openat(dirfd, "does-not-exist", O_RDONLY) < 0);170ATF_REQUIRE_ERRNO(ENOENT,171openat(dirfd, "l3/does-not-exist", O_RDONLY) < 0);172}173174ATF_TC(capmode__negative);175ATF_TC_HEAD(capmode__negative, tc)176{177atf_tc_set_md_var(tc, "descr", "Negative Capability mode testcases");178}179180ATF_TC_BODY(capmode__negative, tc)181{182int subdirfd;183184check_capsicum();185prepare_dotdot_tests();186187ATF_REQUIRE(cap_enter() == 0);188189/* open() not permitted in capability mode */190ATF_REQUIRE_ERRNO(ECAPMODE, open("testdir", O_RDONLY) < 0);191192/* AT_FDCWD not permitted in capability mode */193ATF_REQUIRE_ERRNO(ECAPMODE, openat(AT_FDCWD, "d1/f1", O_RDONLY) < 0);194195/* Relative path above dirfd not capable */196ATF_REQUIRE_ERRNO(ENOTCAPABLE, openat(dirfd, "..", O_RDONLY) < 0);197ATF_REQUIRE((subdirfd = openat(dirfd, "l3", O_RDONLY)) >= 0);198ATF_REQUIRE_ERRNO(ENOTCAPABLE,199openat(subdirfd, "../../f1", O_RDONLY) < 0);200201/* Absolute paths not capable */202ATF_REQUIRE_ERRNO(ENOTCAPABLE, openat(dirfd, abspath, O_RDONLY) < 0);203204/* Symlink above dirfd */205ATF_REQUIRE_ERRNO(ENOTCAPABLE, openat(dirfd, "lup/f1", O_RDONLY) < 0);206}207208ATF_TC(lookup_cap_dotdot__negative);209ATF_TC_HEAD(lookup_cap_dotdot__negative, tc)210{211atf_tc_set_md_var(tc, "descr",212"Validate cap-mode (testdir)/.. lookup fails");213}214215ATF_TC_BODY(lookup_cap_dotdot__negative, tc)216{217cap_rights_t rights;218219check_capsicum();220prepare_dotdot_tests();221222cap_rights_init(&rights, CAP_LOOKUP, CAP_READ);223ATF_REQUIRE(cap_rights_limit(dirfd, &rights) >= 0);224225ATF_REQUIRE(cap_enter() >= 0);226227ATF_REQUIRE_ERRNO(ENOTCAPABLE, openat(dirfd, "..", O_RDONLY) < 0);228ATF_REQUIRE_ERRNO(ENOTCAPABLE, openat(dirfd, "d1/../..", O_RDONLY) < 0);229ATF_REQUIRE_ERRNO(ENOTCAPABLE, openat(dirfd, "../testdir/d1/f1", O_RDONLY) < 0);230}231232ATF_TC(lookup_cap_dotdot__root);233ATF_TC_HEAD(lookup_cap_dotdot__root, tc)234{235atf_tc_set_md_var(tc, "descr", "Validate cap-mode /.. lookup fails");236}237238ATF_TC_BODY(lookup_cap_dotdot__root, tc)239{240int dfd, dfd2;241242check_capsicum();243244dfd = open("/", O_DIRECTORY);245ATF_REQUIRE(dfd >= 0);246247dfd2 = openat(dfd, "..", O_DIRECTORY);248ATF_REQUIRE(dfd2 >= 0);249ATF_REQUIRE(close(dfd2) == 0);250251ATF_REQUIRE(cap_enter() >= 0);252253dfd2 = openat(dfd, "..", O_DIRECTORY);254ATF_REQUIRE_ERRNO(ENOTCAPABLE, openat(dfd, "..", O_DIRECTORY));255}256257ATF_TP_ADD_TCS(tp)258{259260ATF_TP_ADD_TC(tp, openat__basic_positive);261ATF_TP_ADD_TC(tp, openat__basic_negative);262263ATF_TP_ADD_TC(tp, capmode__negative);264265ATF_TP_ADD_TC(tp, lookup_cap_dotdot__basic);266ATF_TP_ADD_TC(tp, lookup_cap_dotdot__advanced);267ATF_TP_ADD_TC(tp, lookup_cap_dotdot__negative);268ATF_TP_ADD_TC(tp, lookup_cap_dotdot__root);269270return (atf_no_error());271}272273274