Path: blob/main/tools/regression/security/cap_test/cap_test_relative.c
48266 views
/*-1* Copyright (c) 2009-2011 Robert N. M. Watson2* Copyright (c) 2011 Jonathan Anderson3* All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND15* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL19* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS20* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)21* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT22* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY23* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF24* SUCH DAMAGE.25*/2627#include <sys/param.h>28#include <sys/capsicum.h>29#include <sys/errno.h>3031#include <err.h>32#include <fcntl.h>33#include <stdlib.h>34#include <string.h>35#include <unistd.h>3637#include "cap_test.h"3839/*40* Test openat(2) in a variety of sitations to ensure that it obeys Capsicum41* "strict relative" rules:42*43* 1. Use strict relative lookups in capability mode or when operating44* relative to a capability.45* 2. When performing strict relative lookups, absolute paths (including46* symlinks to absolute paths) are not allowed, nor are paths containing47* '..' components.48*/49int50test_relative(void)51{52int success = PASSED;53int fd, etc, etc_cap, etc_cap_ro, etc_cap_base, etc_cap_all;54cap_rights_t baserights = CAP_READ | CAP_WRITE | CAP_SEEK | CAP_LOOKUP;55cap_rights_t rights;5657REQUIRE(etc = open("/etc/", O_RDONLY));58CHECK_SYSCALL_SUCCEEDS(cap_getrights, etc, &rights);59CHECK_RIGHTS(rights, CAP_ALL);6061MAKE_CAPABILITY(etc_cap, etc, CAP_READ);62MAKE_CAPABILITY(etc_cap_ro, etc, CAP_READ | CAP_LOOKUP);63MAKE_CAPABILITY(etc_cap_base, etc, baserights);64MAKE_CAPABILITY(etc_cap_all, etc, CAP_MASK_VALID);6566/*67* openat(2) with regular file descriptors in non-capability mode68* should Just Work (tm).69*/70CHECK_SYSCALL_SUCCEEDS(openat, etc, "/etc/passwd", O_RDONLY);71CHECK_SYSCALL_SUCCEEDS(openat, AT_FDCWD, "/etc/passwd", O_RDONLY);72CHECK_SYSCALL_SUCCEEDS(openat, etc, "passwd", O_RDONLY);73CHECK_SYSCALL_SUCCEEDS(openat, etc, "../etc/passwd", O_RDONLY);7475/*76* Lookups relative to capabilities should be strictly relative.77*78* When not in capability mode, we don't actually require CAP_LOOKUP.79*/80CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_ro, "passwd", O_RDONLY);81CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_base, "passwd", O_RDONLY);82CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_all, "passwd", O_RDONLY);8384CHECK_NOTCAPABLE(openat, etc_cap_ro, "../etc/passwd", O_RDONLY);85CHECK_NOTCAPABLE(openat, etc_cap_base, "../etc/passwd", O_RDONLY);8687/*88* This requires discussion: do we treat a capability with89* CAP_MASK_VALID *exactly* like a non-capability file descriptor90* (currently, the implementation says yes)?91*/92CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_all, "../etc/passwd", O_RDONLY);9394/*95* A file opened relative to a capability should itself be a capability.96*/97CHECK_SYSCALL_SUCCEEDS(cap_getrights, etc_cap_base, &rights);9899REQUIRE(fd = openat(etc_cap_base, "passwd", O_RDONLY));100CHECK_SYSCALL_SUCCEEDS(cap_getrights, fd, &rights);101CHECK_RIGHTS(rights, baserights);102103/*104* Enter capability mode; now ALL lookups are strictly relative.105*/106REQUIRE(cap_enter());107108/*109* Relative lookups on regular files or capabilities with CAP_LOOKUP110* ought to succeed.111*/112CHECK_SYSCALL_SUCCEEDS(openat, etc, "passwd", O_RDONLY);113CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_ro, "passwd", O_RDONLY);114CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_base, "passwd", O_RDONLY);115CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_all, "passwd", O_RDONLY);116117/*118* Lookup relative to capabilities without CAP_LOOKUP should fail.119*/120CHECK_NOTCAPABLE(openat, etc_cap, "passwd", O_RDONLY);121122/*123* Absolute lookups should fail.124*/125CHECK_CAPMODE(openat, AT_FDCWD, "/etc/passwd", O_RDONLY);126CHECK_NOTCAPABLE(openat, etc, "/etc/passwd", O_RDONLY);127128/*129* Lookups containing '..' should fail in capability mode.130*/131CHECK_NOTCAPABLE(openat, etc, "../etc/passwd", O_RDONLY);132CHECK_NOTCAPABLE(openat, etc_cap_ro, "../etc/passwd", O_RDONLY);133CHECK_NOTCAPABLE(openat, etc_cap_base, "../etc/passwd", O_RDONLY);134135REQUIRE(fd = openat(etc, "passwd", O_RDONLY));136CHECK_SYSCALL_SUCCEEDS(cap_getrights, fd, &rights);137138/*139* A file opened relative to a capability should itself be a capability.140*/141REQUIRE(fd = openat(etc_cap_base, "passwd", O_RDONLY));142CHECK_SYSCALL_SUCCEEDS(cap_getrights, fd, &rights);143CHECK_RIGHTS(rights, baserights);144145return success;146}147148149