cap_test_relative.c revision 256281
1193323Sed/*- 2193323Sed * Copyright (c) 2009-2011 Robert N. M. Watson 3193323Sed * Copyright (c) 2011 Jonathan Anderson 4193323Sed * All rights reserved. 5193323Sed * 6193323Sed * Redistribution and use in source and binary forms, with or without 7193323Sed * modification, are permitted provided that the following conditions 8193323Sed * are met: 9193323Sed * 1. Redistributions of source code must retain the above copyright 10193323Sed * notice, this list of conditions and the following disclaimer. 11193323Sed * 2. Redistributions in binary form must reproduce the above copyright 12193323Sed * notice, this list of conditions and the following disclaimer in the 13193323Sed * documentation and/or other materials provided with the distribution. 14193323Sed * 15193323Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16193323Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17198090Srdivacky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18193323Sed * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19193323Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20193323Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21193323Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22193323Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23193323Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24193323Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25193323Sed * SUCH DAMAGE. 26193323Sed * 27193323Sed * $FreeBSD: stable/10/tools/regression/security/cap_test/cap_test_relative.c 247605 2013-03-02 00:56:53Z pjd $ 28193323Sed */ 29193323Sed 30193323Sed#include <sys/cdefs.h> 31193323Sed__FBSDID("$FreeBSD: stable/10/tools/regression/security/cap_test/cap_test_relative.c 247605 2013-03-02 00:56:53Z pjd $"); 32193323Sed 33193323Sed#include <sys/param.h> 34193323Sed#include <sys/capability.h> 35193323Sed#include <sys/errno.h> 36193323Sed 37193323Sed#include <err.h> 38193323Sed#include <fcntl.h> 39193323Sed#include <stdlib.h> 40193323Sed#include <string.h> 41193323Sed#include <unistd.h> 42193323Sed 43193323Sed#include "cap_test.h" 44193323Sed 45193323Sed/* 46193323Sed * Test openat(2) in a variety of sitations to ensure that it obeys Capsicum 47193323Sed * "strict relative" rules: 48193323Sed * 49193323Sed * 1. Use strict relative lookups in capability mode or when operating 50193323Sed * relative to a capability. 51193323Sed * 2. When performing strict relative lookups, absolute paths (including 52193323Sed * symlinks to absolute paths) are not allowed, nor are paths containing 53193323Sed * '..' components. 54193323Sed */ 55234353Sdimint 56249423Sdimtest_relative(void) 57234353Sdim{ 58234353Sdim int success = PASSED; 59193323Sed int fd, etc, etc_cap, etc_cap_ro, etc_cap_base, etc_cap_all; 60193323Sed cap_rights_t baserights = CAP_READ | CAP_WRITE | CAP_SEEK | CAP_LOOKUP; 61193323Sed cap_rights_t rights; 62193323Sed 63193323Sed REQUIRE(etc = open("/etc/", O_RDONLY)); 64193323Sed CHECK_SYSCALL_SUCCEEDS(cap_getrights, etc, &rights); 65193323Sed CHECK_RIGHTS(rights, CAP_ALL); 66193323Sed 67193323Sed MAKE_CAPABILITY(etc_cap, etc, CAP_READ); 68193323Sed MAKE_CAPABILITY(etc_cap_ro, etc, CAP_READ | CAP_LOOKUP); 69193323Sed MAKE_CAPABILITY(etc_cap_base, etc, baserights); 70193323Sed MAKE_CAPABILITY(etc_cap_all, etc, CAP_MASK_VALID); 71193323Sed 72193323Sed /* 73193323Sed * openat(2) with regular file descriptors in non-capability mode 74193323Sed * should Just Work (tm). 75193323Sed */ 76193323Sed CHECK_SYSCALL_SUCCEEDS(openat, etc, "/etc/passwd", O_RDONLY); 77193323Sed CHECK_SYSCALL_SUCCEEDS(openat, AT_FDCWD, "/etc/passwd", O_RDONLY); 78193323Sed CHECK_SYSCALL_SUCCEEDS(openat, etc, "passwd", O_RDONLY); 79199481Srdivacky CHECK_SYSCALL_SUCCEEDS(openat, etc, "../etc/passwd", O_RDONLY); 80193323Sed 81193323Sed /* 82193323Sed * Lookups relative to capabilities should be strictly relative. 83193323Sed * 84199481Srdivacky * When not in capability mode, we don't actually require CAP_LOOKUP. 85193323Sed */ 86193323Sed CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_ro, "passwd", O_RDONLY); 87193323Sed CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_base, "passwd", O_RDONLY); 88193323Sed CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_all, "passwd", O_RDONLY); 89193323Sed 90193323Sed CHECK_NOTCAPABLE(openat, etc_cap_ro, "../etc/passwd", O_RDONLY); 91193323Sed CHECK_NOTCAPABLE(openat, etc_cap_base, "../etc/passwd", O_RDONLY); 92199481Srdivacky 93193323Sed /* 94193323Sed * This requires discussion: do we treat a capability with 95193323Sed * CAP_MASK_VALID *exactly* like a non-capability file descriptor 96193323Sed * (currently, the implementation says yes)? 97193323Sed */ 98193323Sed CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_all, "../etc/passwd", O_RDONLY); 99193323Sed 100193323Sed /* 101193323Sed * A file opened relative to a capability should itself be a capability. 102193323Sed */ 103193323Sed CHECK_SYSCALL_SUCCEEDS(cap_getrights, etc_cap_base, &rights); 104193323Sed 105193323Sed REQUIRE(fd = openat(etc_cap_base, "passwd", O_RDONLY)); 106193323Sed CHECK_SYSCALL_SUCCEEDS(cap_getrights, fd, &rights); 107193323Sed CHECK_RIGHTS(rights, baserights); 108193323Sed 109193323Sed /* 110193323Sed * Enter capability mode; now ALL lookups are strictly relative. 111193323Sed */ 112193323Sed REQUIRE(cap_enter()); 113193323Sed 114193323Sed /* 115193323Sed * Relative lookups on regular files or capabilities with CAP_LOOKUP 116193323Sed * ought to succeed. 117193323Sed */ 118193323Sed CHECK_SYSCALL_SUCCEEDS(openat, etc, "passwd", O_RDONLY); 119193323Sed CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_ro, "passwd", O_RDONLY); 120218893Sdim CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_base, "passwd", O_RDONLY); 121218893Sdim CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_all, "passwd", O_RDONLY); 122198090Srdivacky 123198090Srdivacky /* 124193323Sed * Lookup relative to capabilities without CAP_LOOKUP should fail. 125193323Sed */ 126193323Sed CHECK_NOTCAPABLE(openat, etc_cap, "passwd", O_RDONLY); 127193323Sed 128193323Sed /* 129193323Sed * Absolute lookups should fail. 130193323Sed */ 131193323Sed CHECK_CAPMODE(openat, AT_FDCWD, "/etc/passwd", O_RDONLY); 132193323Sed CHECK_NOTCAPABLE(openat, etc, "/etc/passwd", O_RDONLY); 133193323Sed 134224145Sdim /* 135193323Sed * Lookups containing '..' should fail in capability mode. 136193323Sed */ 137193323Sed CHECK_NOTCAPABLE(openat, etc, "../etc/passwd", O_RDONLY); 138193323Sed CHECK_NOTCAPABLE(openat, etc_cap_ro, "../etc/passwd", O_RDONLY); 139193323Sed CHECK_NOTCAPABLE(openat, etc_cap_base, "../etc/passwd", O_RDONLY); 140193323Sed 141193323Sed REQUIRE(fd = openat(etc, "passwd", O_RDONLY)); 142193323Sed CHECK_SYSCALL_SUCCEEDS(cap_getrights, fd, &rights); 143193323Sed 144193323Sed /* 145193323Sed * A file opened relative to a capability should itself be a capability. 146193323Sed */ 147193323Sed REQUIRE(fd = openat(etc_cap_base, "passwd", O_RDONLY)); 148193323Sed CHECK_SYSCALL_SUCCEEDS(cap_getrights, fd, &rights); 149193323Sed CHECK_RIGHTS(rights, baserights); 150218893Sdim 151193323Sed return success; 152193323Sed} 153193323Sed