Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F163409015
D19758.id55700.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
20 KB
Referenced Files
None
Subscribers
None
D19758.id55700.diff
View Options
Index: contrib/capsicum-test/capsicum-test-main.cc
===================================================================
--- contrib/capsicum-test/capsicum-test-main.cc
+++ contrib/capsicum-test/capsicum-test-main.cc
@@ -2,16 +2,25 @@
#ifdef __linux__
#include <sys/vfs.h>
#include <linux/magic.h>
+#elif defined(__FreeBSD__)
+#include <sys/sysctl.h>
#endif
#include <ctype.h>
#include <errno.h>
+#include <libgen.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include <iostream>
#include "gtest/gtest.h"
#include "capsicum-test.h"
+// For versions of googletest that lack GTEST_SKIP.
+#ifndef GTEST_SKIP
+#define GTEST_SKIP GTEST_FAIL
+#endif
+
std::string tmpdir;
class SetupEnvironment : public ::testing::Environment
@@ -19,6 +28,7 @@
public:
SetupEnvironment() : teardown_tmpdir_(false) {}
void SetUp() override {
+ CheckCapsicumSupport();
if (tmpdir.empty()) {
std::cerr << "Generating temporary directory root: ";
CreateTemporaryRoot();
@@ -27,6 +37,31 @@
}
std::cerr << tmpdir << std::endl;
}
+ void CheckCapsicumSupport() {
+#ifdef __FreeBSD__
+ int rc;
+ bool trap_enotcap_enabled;
+ size_t trap_enotcap_enabled_len = sizeof(trap_enotcap_enabled);
+
+ if (feature_present("security_capabilities") == 0) {
+ GTEST_SKIP() << "Skipping tests because capsicum support is not "
+ << "enabled in the kernel.";
+ }
+ // If this OID is enabled, it will send SIGTRAP to the process when
+ // `ENOTCAPABLE` is returned.
+ const char *oid = "kern.trap_enotcap";
+ rc = sysctlbyname(oid, &trap_enotcap_enabled, &trap_enotcap_enabled_len,
+ nullptr, 0);
+ if (rc != 0) {
+ GTEST_FAIL() << "sysctlbyname failed: " << strerror(errno);
+ }
+ if (trap_enotcap_enabled) {
+ GTEST_SKIP() << "Debug sysctl, " << oid << ", enabled. "
+ << "Skipping tests because its enablement invalidates the "
+ << "test results.";
+ }
+#endif /* FreeBSD */
+ }
void CreateTemporaryRoot() {
char *tmpdir_name = tempnam(nullptr, "cptst");
@@ -47,7 +82,27 @@
bool teardown_tmpdir_;
};
+std::string capsicum_test_bindir;
+
int main(int argc, char* argv[]) {
+ // Set up the test program path, so capsicum-test can find programs, like
+ // mini-me* when executed from an absolute path.
+ {
+ char *new_path, *old_path, *program_name;
+
+ program_name = strdup(argv[0]);
+ assert(program_name);
+ capsicum_test_bindir = std::string(dirname(program_name));
+ free(program_name);
+
+ old_path = getenv("PATH");
+ assert(old_path);
+
+ assert(asprintf(&new_path, "%s:%s", capsicum_test_bindir.c_str(),
+ old_path) > 0);
+ assert(setenv("PATH", new_path, 1) == 0);
+ }
+
::testing::InitGoogleTest(&argc, argv);
for (int ii = 1; ii < argc; ii++) {
if (strcmp(argv[ii], "-v") == 0) {
Index: contrib/capsicum-test/capsicum.h
===================================================================
--- contrib/capsicum-test/capsicum.h
+++ contrib/capsicum-test/capsicum.h
@@ -167,4 +167,9 @@
#endif /* new/old style rights manipulation */
+#ifdef __cplusplus
+#include <string>
+extern std::string capsicum_test_bindir;
+#endif
+
#endif /*__CAPSICUM_H__*/
Index: contrib/capsicum-test/fexecve.cc
===================================================================
--- contrib/capsicum-test/fexecve.cc
+++ contrib/capsicum-test/fexecve.cc
@@ -1,12 +1,12 @@
-#include <errno.h>
-#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
+#include <errno.h>
#include <fcntl.h>
-#include <unistd.h>
#include <limits.h>
#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
#include <sstream>
@@ -14,41 +14,76 @@
#include "capsicum.h"
#include "capsicum-test.h"
-// We need a program to exec(), but for fexecve() to work in capability
-// mode that program needs to be statically linked (otherwise ld.so will
-// attempt to traverse the filesystem to load (e.g.) /lib/libc.so and
-// fail).
-#define EXEC_PROG "./mini-me"
-#define EXEC_PROG_NOEXEC EXEC_PROG ".noexec"
-#define EXEC_PROG_SETUID EXEC_PROG ".setuid"
-
// Arguments to use in execve() calls.
-static char* argv_pass[] = {(char*)EXEC_PROG, (char*)"--pass", NULL};
-static char* argv_fail[] = {(char*)EXEC_PROG, (char*)"--fail", NULL};
-static char* argv_checkroot[] = {(char*)EXEC_PROG, (char*)"--checkroot", NULL};
static char* null_envp[] = {NULL};
class Execve : public ::testing::Test {
public:
- Execve() : exec_fd_(open(EXEC_PROG, O_RDONLY)) {
+ Execve() : exec_fd_(-1) {
+ // We need a program to exec(), but for fexecve() to work in capability
+ // mode that program needs to be statically linked (otherwise ld.so will
+ // attempt to traverse the filesystem to load (e.g.) /lib/libc.so and
+ // fail).
+ exec_prog_ = capsicum_test_bindir + "/mini-me";
+ exec_prog_noexec_ = capsicum_test_bindir + "/mini-me.noexec";
+ exec_prog_setuid_ = capsicum_test_bindir + "/mini-me.setuid";
+
+ exec_fd_ = open(exec_prog_.c_str(), O_RDONLY);
if (exec_fd_ < 0) {
- fprintf(stderr, "Error! Failed to open %s\n", EXEC_PROG);
+ fprintf(stderr, "Error! Failed to open %s\n", exec_prog_.c_str());
+ }
+ argv_checkroot_[0] = (char*)exec_prog_.c_str();
+ argv_fail_[0] = (char*)exec_prog_.c_str();
+ argv_pass_[0] = (char*)exec_prog_.c_str();
+ }
+ ~Execve() {
+ if (exec_fd_ >= 0) {
+ close(exec_fd_);
+ exec_fd_ = -1;
}
}
- ~Execve() { if (exec_fd_ >= 0) close(exec_fd_); }
protected:
+ char* argv_checkroot_[3] = {nullptr, (char*)"--checkroot", nullptr};
+ char* argv_fail_[3] = {nullptr, (char*)"--fail", nullptr};
+ char* argv_pass_[3] = {nullptr, (char*)"--pass", nullptr};
+ std::string exec_prog_, exec_prog_noexec_, exec_prog_setuid_;
int exec_fd_;
};
+class Fexecve : public Execve {
+ public:
+ Fexecve() : Execve() {}
+};
+
+class FexecveWithScript : public Fexecve {
+ public:
+ FexecveWithScript() :
+ Fexecve(), temp_script_filename_(TmpFile("cap_sh_script")) {}
+
+ void SetUp() override {
+ // First, build an executable shell script
+ int fd = open(temp_script_filename_, O_RDWR|O_CREAT, 0755);
+ EXPECT_OK(fd);
+ const char* contents = "#!/bin/sh\nexit 99\n";
+ EXPECT_OK(write(fd, contents, strlen(contents)));
+ close(fd);
+ }
+ void TearDown() override {
+ (void)::unlink(temp_script_filename_);
+ }
+
+ const char *temp_script_filename_;
+};
+
FORK_TEST_F(Execve, BasicFexecve) {
- EXPECT_OK(fexecve_(exec_fd_, argv_pass, null_envp));
+ EXPECT_OK(fexecve_(exec_fd_, argv_pass_, null_envp));
// Should not reach here, exec() takes over.
EXPECT_TRUE(!"fexecve() should never return");
}
FORK_TEST_F(Execve, InCapMode) {
EXPECT_OK(cap_enter());
- EXPECT_OK(fexecve_(exec_fd_, argv_pass, null_envp));
+ EXPECT_OK(fexecve_(exec_fd_, argv_pass_, null_envp));
// Should not reach here, exec() takes over.
EXPECT_TRUE(!"fexecve() should never return");
}
@@ -60,7 +95,7 @@
cap_rights_t rights;
cap_rights_init(&rights, 0);
EXPECT_OK(cap_rights_limit(cap_fd, &rights));
- EXPECT_EQ(-1, fexecve_(cap_fd, argv_fail, null_envp));
+ EXPECT_EQ(-1, fexecve_(cap_fd, argv_fail_, null_envp));
EXPECT_EQ(ENOTCAPABLE, errno);
}
@@ -73,59 +108,54 @@
// rights -- just CAP_FEXECVE|CAP_READ or CAP_FEXECVE would be preferable.
cap_rights_init(&rights, CAP_FEXECVE, CAP_LOOKUP, CAP_READ);
EXPECT_OK(cap_rights_limit(cap_fd, &rights));
- EXPECT_OK(fexecve_(cap_fd, argv_pass, null_envp));
+ EXPECT_OK(fexecve_(cap_fd, argv_pass_, null_envp));
// Should not reach here, exec() takes over.
EXPECT_TRUE(!"fexecve() should have succeeded");
}
-FORK_TEST(Fexecve, ExecutePermissionCheck) {
- int fd = open(EXEC_PROG_NOEXEC, O_RDONLY);
+FORK_TEST_F(Fexecve, ExecutePermissionCheck) {
+ int fd = open(exec_prog_noexec_.c_str(), O_RDONLY);
EXPECT_OK(fd);
if (fd >= 0) {
struct stat data;
EXPECT_OK(fstat(fd, &data));
EXPECT_EQ((mode_t)0, data.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH));
- EXPECT_EQ(-1, fexecve_(fd, argv_fail, null_envp));
+ EXPECT_EQ(-1, fexecve_(fd, argv_fail_, null_envp));
EXPECT_EQ(EACCES, errno);
close(fd);
}
}
-FORK_TEST(Fexecve, SetuidIgnored) {
+FORK_TEST_F(Fexecve, SetuidIgnored) {
if (geteuid() == 0) {
TEST_SKIPPED("requires non-root");
return;
}
- int fd = open(EXEC_PROG_SETUID, O_RDONLY);
+ int fd = open(exec_prog_setuid_.c_str(), O_RDONLY);
EXPECT_OK(fd);
EXPECT_OK(cap_enter());
if (fd >= 0) {
struct stat data;
EXPECT_OK(fstat(fd, &data));
EXPECT_EQ((mode_t)S_ISUID, data.st_mode & S_ISUID);
- EXPECT_OK(fexecve_(fd, argv_checkroot, null_envp));
+ EXPECT_OK(fexecve_(fd, argv_checkroot_, null_envp));
// Should not reach here, exec() takes over.
EXPECT_TRUE(!"fexecve() should have succeeded");
close(fd);
}
}
-FORK_TEST(Fexecve, ExecveFailure) {
+FORK_TEST_F(Fexecve, ExecveFailure) {
EXPECT_OK(cap_enter());
- EXPECT_EQ(-1, execve(argv_fail[0], argv_fail, null_envp));
+ EXPECT_EQ(-1, execve(argv_fail_[0], argv_fail_, null_envp));
EXPECT_EQ(ECAPMODE, errno);
}
-FORK_TEST_ON(Fexecve, CapModeScriptFail, TmpFile("cap_sh_script")) {
- // First, build an executable shell script
- int fd = open(TmpFile("cap_sh_script"), O_RDWR|O_CREAT, 0755);
- EXPECT_OK(fd);
- const char* contents = "#!/bin/sh\nexit 99\n";
- EXPECT_OK(write(fd, contents, strlen(contents)));
- close(fd);
+FORK_TEST_F(FexecveWithScript, CapModeScriptFail) {
+ int fd;
// Open the script file, with CAP_FEXECVE rights.
- fd = open(TmpFile("cap_sh_script"), O_RDONLY);
+ fd = open(temp_script_filename_, O_RDONLY);
cap_rights_t rights;
cap_rights_init(&rights, CAP_FEXECVE, CAP_READ, CAP_SEEK);
EXPECT_OK(cap_rights_limit(fd, &rights));
@@ -133,12 +163,17 @@
EXPECT_OK(cap_enter()); // Enter capability mode
// Attempt fexecve; should fail, because "/bin/sh" is inaccessible.
- EXPECT_EQ(-1, fexecve_(fd, argv_pass, null_envp));
+ EXPECT_EQ(-1, fexecve_(fd, argv_pass_, null_envp));
}
#ifdef HAVE_EXECVEAT
-TEST(Execveat, NoUpwardTraversal) {
- char *abspath = realpath(EXEC_PROG, NULL);
+class Execveat : public Execve {
+ public:
+ Execveat() : Execve() {}
+};
+
+TEST_F(Execveat, NoUpwardTraversal) {
+ char *abspath = realpath(exec_prog_, NULL);
char cwd[1024];
getcwd(cwd, sizeof(cwd));
@@ -148,9 +183,9 @@
EXPECT_OK(cap_enter()); // Enter capability mode.
// Can't execveat() an absolute path, even relative to a dfd.
EXPECT_SYSCALL_FAIL(ECAPMODE,
- execveat(AT_FDCWD, abspath, argv_pass, null_envp, 0));
+ execveat(AT_FDCWD, abspath, argv_pass_, null_envp, 0));
EXPECT_SYSCALL_FAIL(E_NO_TRAVERSE_CAPABILITY,
- execveat(dfd, abspath, argv_pass, null_envp, 0));
+ execveat(dfd, abspath, argv_pass_, null_envp, 0));
// Can't execveat() a relative path ("../<dir>/./<exe>").
char *p = cwd + strlen(cwd);
@@ -158,9 +193,9 @@
char buffer[1024] = "../";
strcat(buffer, ++p);
strcat(buffer, "/");
- strcat(buffer, EXEC_PROG);
+ strcat(buffer, exec_prog_);
EXPECT_SYSCALL_FAIL(E_NO_TRAVERSE_CAPABILITY,
- execveat(dfd, buffer, argv_pass, null_envp, 0));
+ execveat(dfd, buffer, argv_pass_, null_envp, 0));
exit(HasFailure() ? 99 : 123);
}
int status;
Index: contrib/capsicum-test/openat.cc
===================================================================
--- contrib/capsicum-test/openat.cc
+++ contrib/capsicum-test/openat.cc
@@ -148,7 +148,7 @@
}
#define TOPDIR "cap_topdir"
-#define SUBDIR_ABS TOPDIR "/subdir"
+#define SUBDIR TOPDIR "/subdir"
class OpenatTest : public ::testing::Test {
public:
// Build a collection of files, subdirs and symlinks:
@@ -156,20 +156,20 @@
// /topfile
// /subdir/
// /subdir/bottomfile
- // /symlink.samedir -> topfile
- // /dsymlink.samedir -> ./
- // /symlink.down -> subdir/bottomfile
- // /dsymlink.down -> subdir/
- // /symlink.absolute_in -> /tmp/cap_topdir/topfile
- // /dsymlink.absolute_in -> /tmp/cap_topdir/
- // /symlink.absolute_out -> /etc/passwd
- // /dsymlink.absolute_out -> /etc/
- // /symlink.relative_in -> ../../tmp/cap_topdir/topfile
- // /dsymlink.relative_in -> ../../tmp/cap_topdir/
- // /symlink.relative_out -> ../../etc/passwd
- // /dsymlink.relative_out -> ../../etc/
- // /subdir/symlink.up -> ../topfile
- // /subdir/dsymlink.up -> ../
+ // /symlink.samedir -> topfile
+ // /dsymlink.samedir -> ./
+ // /symlink.down -> subdir/bottomfile
+ // /dsymlink.down -> subdir/
+ // /symlink.absolute_out -> /etc/passwd
+ // /dsymlink.absolute_out -> /etc/
+ // /symlink.relative_in -> ../../tmp/cap_topdir/topfile
+ // /dsymlink.relative_in -> ../../tmp/cap_topdir/
+ // /symlink.relative_out -> ../../etc/passwd
+ // /dsymlink.relative_out -> ../../etc/
+ // /subdir/dsymlink.absolute_in -> /tmp/cap_topdir/
+ // /subdir/dsymlink.up -> ../
+ // /subdir/symlink.absolute_in -> /tmp/cap_topdir/topfile
+ // /subdir/symlink.up -> ../topfile
// (In practice, this is a little more complicated because tmpdir might
// not be "/tmp".)
OpenatTest() {
@@ -179,7 +179,7 @@
if (rc < 0) {
EXPECT_EQ(EEXIST, errno);
}
- rc = mkdir(TmpFile(SUBDIR_ABS), 0755);
+ rc = mkdir(TmpFile(SUBDIR), 0755);
EXPECT_OK(rc);
if (rc < 0) {
EXPECT_EQ(EEXIST, errno);
@@ -197,34 +197,34 @@
// Create normal files in each.
CreateFile(TmpFile(TOPDIR "/topfile"), "Top-level file");
- CreateFile(TmpFile(SUBDIR_ABS "/bottomfile"), "File in subdirectory");
+ CreateFile(TmpFile(SUBDIR "/bottomfile"), "File in subdirectory");
// Create various symlinks to files.
EXPECT_OK(symlink("topfile", TmpFile(TOPDIR "/symlink.samedir")));
EXPECT_OK(symlink("subdir/bottomfile", TmpFile(TOPDIR "/symlink.down")));
- EXPECT_OK(symlink(TmpFile(TOPDIR "/topfile"), TmpFile(TOPDIR "/symlink.absolute_in")));
+ EXPECT_OK(symlink(TmpFile(TOPDIR "/topfile"), TmpFile(SUBDIR "/symlink.absolute_in")));
EXPECT_OK(symlink("/etc/passwd", TmpFile(TOPDIR "/symlink.absolute_out")));
std::string dots2top = dots2root + TmpFile(TOPDIR "/topfile");
EXPECT_OK(symlink(dots2top.c_str(), TmpFile(TOPDIR "/symlink.relative_in")));
std::string dots2passwd = dots2root + "/etc/passwd";
EXPECT_OK(symlink(dots2passwd.c_str(), TmpFile(TOPDIR "/symlink.relative_out")));
- EXPECT_OK(symlink("../topfile", TmpFile(SUBDIR_ABS "/symlink.up")));
+ EXPECT_OK(symlink("../topfile", TmpFile(SUBDIR "/symlink.up")));
// Create various symlinks to directories.
EXPECT_OK(symlink("./", TmpFile(TOPDIR "/dsymlink.samedir")));
EXPECT_OK(symlink("subdir/", TmpFile(TOPDIR "/dsymlink.down")));
- EXPECT_OK(symlink(TmpFile(TOPDIR "/"), TmpFile(TOPDIR "/dsymlink.absolute_in")));
+ EXPECT_OK(symlink(TmpFile(TOPDIR "/"), TmpFile(SUBDIR "/dsymlink.absolute_in")));
EXPECT_OK(symlink("/etc/", TmpFile(TOPDIR "/dsymlink.absolute_out")));
std::string dots2cwd = dots2root + tmpdir + "/";
EXPECT_OK(symlink(dots2cwd.c_str(), TmpFile(TOPDIR "/dsymlink.relative_in")));
std::string dots2etc = dots2root + "/etc/";
EXPECT_OK(symlink(dots2etc.c_str(), TmpFile(TOPDIR "/dsymlink.relative_out")));
- EXPECT_OK(symlink("../", TmpFile(SUBDIR_ABS "/dsymlink.up")));
+ EXPECT_OK(symlink("../", TmpFile(SUBDIR "/dsymlink.up")));
// Open directory FDs for those directories and for cwd.
dir_fd_ = open(TmpFile(TOPDIR), O_RDONLY);
EXPECT_OK(dir_fd_);
- sub_fd_ = open(TmpFile(SUBDIR_ABS), O_RDONLY);
+ sub_fd_ = open(TmpFile(SUBDIR), O_RDONLY);
EXPECT_OK(sub_fd_);
cwd_ = openat(AT_FDCWD, ".", O_RDONLY);
EXPECT_OK(cwd_);
@@ -236,23 +236,23 @@
close(cwd_);
close(sub_fd_);
close(dir_fd_);
- unlink(TmpFile(SUBDIR_ABS "/symlink.up"));
- unlink(TmpFile(TOPDIR "/symlink.absolute_in"));
+ unlink(TmpFile(SUBDIR "/symlink.up"));
+ unlink(TmpFile(SUBDIR "/symlink.absolute_in"));
unlink(TmpFile(TOPDIR "/symlink.absolute_out"));
unlink(TmpFile(TOPDIR "/symlink.relative_in"));
unlink(TmpFile(TOPDIR "/symlink.relative_out"));
unlink(TmpFile(TOPDIR "/symlink.down"));
unlink(TmpFile(TOPDIR "/symlink.samedir"));
- unlink(TmpFile(SUBDIR_ABS "/dsymlink.up"));
- unlink(TmpFile(TOPDIR "/dsymlink.absolute_in"));
+ unlink(TmpFile(SUBDIR "/dsymlink.up"));
+ unlink(TmpFile(SUBDIR "/dsymlink.absolute_in"));
unlink(TmpFile(TOPDIR "/dsymlink.absolute_out"));
unlink(TmpFile(TOPDIR "/dsymlink.relative_in"));
unlink(TmpFile(TOPDIR "/dsymlink.relative_out"));
unlink(TmpFile(TOPDIR "/dsymlink.down"));
unlink(TmpFile(TOPDIR "/dsymlink.samedir"));
- unlink(TmpFile(SUBDIR_ABS "/bottomfile"));
+ unlink(TmpFile(SUBDIR "/bottomfile"));
unlink(TmpFile(TOPDIR "/topfile"));
- rmdir(TmpFile(SUBDIR_ABS));
+ rmdir(TmpFile(SUBDIR));
rmdir(TmpFile(TOPDIR));
}
@@ -281,18 +281,18 @@
// Should only be able to open symlinks that stay within the directory.
EXPECT_OPEN_OK(openat(dir_fd_, "symlink.samedir", O_RDONLY|oflag));
EXPECT_OPEN_OK(openat(dir_fd_, "symlink.down", O_RDONLY|oflag));
- EXPECT_OPENAT_FAIL_TRAVERSAL(dir_fd_, "symlink.absolute_in", O_RDONLY|oflag);
EXPECT_OPENAT_FAIL_TRAVERSAL(dir_fd_, "symlink.absolute_out", O_RDONLY|oflag);
EXPECT_OPENAT_FAIL_TRAVERSAL(dir_fd_, "symlink.relative_in", O_RDONLY|oflag);
EXPECT_OPENAT_FAIL_TRAVERSAL(dir_fd_, "symlink.relative_out", O_RDONLY|oflag);
+ EXPECT_OPENAT_FAIL_TRAVERSAL(sub_fd_, "symlink.absolute_in", O_RDONLY|oflag);
EXPECT_OPENAT_FAIL_TRAVERSAL(sub_fd_, "symlink.up", O_RDONLY|oflag);
EXPECT_OPEN_OK(openat(dir_fd_, "dsymlink.samedir/topfile", O_RDONLY|oflag));
EXPECT_OPEN_OK(openat(dir_fd_, "dsymlink.down/bottomfile", O_RDONLY|oflag));
- EXPECT_OPENAT_FAIL_TRAVERSAL(dir_fd_, "dsymlink.absolute_in/topfile", O_RDONLY|oflag);
EXPECT_OPENAT_FAIL_TRAVERSAL(dir_fd_, "dsymlink.absolute_out/passwd", O_RDONLY|oflag);
EXPECT_OPENAT_FAIL_TRAVERSAL(dir_fd_, "dsymlink.relative_in/topfile", O_RDONLY|oflag);
EXPECT_OPENAT_FAIL_TRAVERSAL(dir_fd_, "dsymlink.relative_out/passwd", O_RDONLY|oflag);
+ EXPECT_OPENAT_FAIL_TRAVERSAL(sub_fd_, "dsymlink.absolute_in/topfile", O_RDONLY|oflag);
EXPECT_OPENAT_FAIL_TRAVERSAL(sub_fd_, "dsymlink.up/topfile", O_RDONLY|oflag);
// Although recall that O_NOFOLLOW prevents symlink following in final component.
@@ -310,10 +310,10 @@
// Any kind of symlink can be opened relative to an ordinary directory FD.
EXPECT_OPEN_OK(openat(dir_fd_, "symlink.samedir", O_RDONLY));
EXPECT_OPEN_OK(openat(dir_fd_, "symlink.down", O_RDONLY));
- EXPECT_OPEN_OK(openat(dir_fd_, "symlink.absolute_in", O_RDONLY));
EXPECT_OPEN_OK(openat(dir_fd_, "symlink.absolute_out", O_RDONLY));
EXPECT_OPEN_OK(openat(dir_fd_, "symlink.relative_in", O_RDONLY));
EXPECT_OPEN_OK(openat(dir_fd_, "symlink.relative_out", O_RDONLY));
+ EXPECT_OPEN_OK(openat(sub_fd_, "symlink.absolute_in", O_RDONLY));
EXPECT_OPEN_OK(openat(sub_fd_, "symlink.up", O_RDONLY));
// Now make both DFDs into Capsicum capabilities.
Index: tests/sys/capsicum/Makefile
===================================================================
--- tests/sys/capsicum/Makefile
+++ tests/sys/capsicum/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <src.opts.mk>
+
TESTSDIR= ${TESTSBASE}/sys/capsicum
ATF_TESTS_C+= bindat_connectat
@@ -7,6 +9,49 @@
CFLAGS+= -I${SRCTOP}/tests
+.if ${MK_GOOGLETEST} != no
+
+.PATH: ${SRCTOP}/contrib/capsicum-test
+
+GTESTS+= capsicum-test
+
+SRCS.capsicum-test+= \
+ capsicum-test-main.cc \
+ capsicum-test.cc \
+ capability-fd.cc \
+ fexecve.cc \
+ procdesc.cc \
+ capmode.cc \
+ fcntl.cc \
+ ioctl.cc \
+ openat.cc \
+ sysctl.cc \
+ select.cc \
+ mqueue.cc \
+ socket.cc \
+ sctp.cc \
+ capability-fd-pair.cc \
+ overhead.cc \
+ rename.cc
+
+LIBADD.capsicum-test+= gtest pthread
+TEST_METADATA.capsicum-test= required_user="unprivileged"
+
+.for p in mini-me mini-me.noexec mini-me.setuid
+PROGS+= $p
+NO_SHARED.$p=
+SRCS.$p= mini-me.c
+.endfor
+
+BINDIR= ${TESTSDIR}
+
+BINMODE.mini-me.noexec= ${NOBINMODE}
+BINMODE.mini-me.setuid= 4555
+
+WARNS.capsicum-test= 3
+
+.endif
+
WARNS?= 6
.include <bsd.test.mk>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jul 23, 11:14 PM (16 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35419101
Default Alt Text
D19758.id55700.diff (20 KB)
Attached To
Mode
D19758: Integrate capsicum-test into the FreeBSD test suite
Attached
Detach File
Event Timeline
Log In to Comment