path_test: Add a few new test cases

MFC after:	1 week
Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Mark Johnston 2021-05-04 08:56:31 -04:00
parent 8bde6d15d1
commit b59851e99c

View File

@ -38,10 +38,12 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/memrange.h> #include <sys/memrange.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/ptrace.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <sys/un.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <aio.h> #include <aio.h>
@ -49,6 +51,7 @@
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <poll.h> #include <poll.h>
#include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
@ -205,6 +208,47 @@ ATF_TC_BODY(path_capsicum, tc)
waitchild(child, 4); waitchild(child, 4);
} }
/* Make sure that ptrace(PT_COREDUMP) cannot be used to write to a path fd. */
ATF_TC_WITHOUT_HEAD(path_coredump);
ATF_TC_BODY(path_coredump, tc)
{
char path[PATH_MAX];
struct ptrace_coredump pc;
int error, pathfd, status;
pid_t child;
mktdir(path, "path_coredump.XXXXXX");
child = fork();
ATF_REQUIRE_MSG(child != -1, FMT_ERR("fork"));
if (child == 0) {
while (true)
(void)sleep(1);
}
pathfd = open(path, O_PATH);
ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
error = ptrace(PT_ATTACH, child, 0, 0);
ATF_REQUIRE_MSG(error == 0, FMT_ERR("ptrace"));
error = waitpid(child, &status, 0);
ATF_REQUIRE_MSG(error != -1, FMT_ERR("waitpid"));
ATF_REQUIRE_MSG(WIFSTOPPED(status), "unexpected status %d", status);
pc.pc_fd = pathfd;
pc.pc_flags = 0;
pc.pc_limit = 0;
error = ptrace(PT_COREDUMP, child, (void *)&pc, sizeof(pc));
ATF_REQUIRE_ERRNO(EBADF, error == -1);
error = ptrace(PT_DETACH, child, 0, 0);
ATF_REQUIRE_MSG(error == 0, FMT_ERR("ptrace"));
ATF_REQUIRE_MSG(kill(child, SIGKILL) == 0, FMT_ERR("kill"));
CHECKED_CLOSE(pathfd);
}
/* Verify operations on directory path descriptors. */ /* Verify operations on directory path descriptors. */
ATF_TC_WITHOUT_HEAD(path_directory); ATF_TC_WITHOUT_HEAD(path_directory);
ATF_TC_BODY(path_directory, tc) ATF_TC_BODY(path_directory, tc)
@ -506,6 +550,33 @@ ATF_TC_BODY(path_fexecve, tc)
ATF_REQUIRE_ERRNO(EACCES, pathfd < 0); ATF_REQUIRE_ERRNO(EACCES, pathfd < 0);
} }
/* Make sure that O_PATH restrictions apply to named pipes as well. */
ATF_TC_WITHOUT_HEAD(path_fifo);
ATF_TC_BODY(path_fifo, tc)
{
char path[PATH_MAX], buf[BUFSIZ];
struct kevent ev;
int kq, pathfd;
snprintf(path, sizeof(path), "path_fifo.XXXXXX");
ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp"));
ATF_REQUIRE_MSG(mkfifo(path, 0666) == 0, FMT_ERR("mkfifo"));
pathfd = open(path, O_PATH);
ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
memset(buf, 0, sizeof(buf));
ATF_REQUIRE_ERRNO(EBADF, write(pathfd, buf, sizeof(buf)));
ATF_REQUIRE_ERRNO(EBADF, read(pathfd, buf, sizeof(buf)));
kq = kqueue();
ATF_REQUIRE_MSG(kq >= 0, FMT_ERR("kqueue"));
EV_SET(&ev, pathfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
ATF_REQUIRE_ERRNO(EBADF, kevent(kq, &ev, 1, NULL, 0, NULL) == -1);
CHECKED_CLOSE(pathfd);
}
/* Files may be unlinked using a path fd. */ /* Files may be unlinked using a path fd. */
ATF_TC_WITHOUT_HEAD(path_funlinkat); ATF_TC_WITHOUT_HEAD(path_funlinkat);
ATF_TC_BODY(path_funlinkat, tc) ATF_TC_BODY(path_funlinkat, tc)
@ -755,11 +826,38 @@ ATF_TC_BODY(path_rights, tc)
CHECKED_CLOSE(sd[1]); CHECKED_CLOSE(sd[1]);
} }
/* Verify that a local socket can't be opened with O_PATH. */
ATF_TC_WITHOUT_HEAD(path_unix);
ATF_TC_BODY(path_unix, tc)
{
char path[PATH_MAX];
struct sockaddr_un sun;
int pathfd, sd;
snprintf(path, sizeof(path), "path_unix.XXXXXX");
ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp"));
sd = socket(PF_LOCAL, SOCK_STREAM, 0);
ATF_REQUIRE_MSG(sd >= 0, FMT_ERR("socket"));
memset(&sun, 0, sizeof(sun));
sun.sun_family = PF_LOCAL;
(void)strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
ATF_REQUIRE_MSG(bind(sd, (struct sockaddr *)&sun, SUN_LEN(&sun)) == 0,
FMT_ERR("bind"));
pathfd = open(path, O_RDONLY);
ATF_REQUIRE_ERRNO(EOPNOTSUPP, pathfd < 0);
CHECKED_CLOSE(sd);
}
ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TCS(tp)
{ {
ATF_TP_ADD_TC(tp, path_access); ATF_TP_ADD_TC(tp, path_access);
ATF_TP_ADD_TC(tp, path_aio); ATF_TP_ADD_TC(tp, path_aio);
ATF_TP_ADD_TC(tp, path_capsicum); ATF_TP_ADD_TC(tp, path_capsicum);
ATF_TP_ADD_TC(tp, path_coredump);
ATF_TP_ADD_TC(tp, path_directory); ATF_TP_ADD_TC(tp, path_directory);
ATF_TP_ADD_TC(tp, path_directory_not_root); ATF_TP_ADD_TC(tp, path_directory_not_root);
ATF_TP_ADD_TC(tp, path_empty); ATF_TP_ADD_TC(tp, path_empty);
@ -768,11 +866,13 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, path_event); ATF_TP_ADD_TC(tp, path_event);
ATF_TP_ADD_TC(tp, path_fcntl); ATF_TP_ADD_TC(tp, path_fcntl);
ATF_TP_ADD_TC(tp, path_fexecve); ATF_TP_ADD_TC(tp, path_fexecve);
ATF_TP_ADD_TC(tp, path_fifo);
ATF_TP_ADD_TC(tp, path_funlinkat); ATF_TP_ADD_TC(tp, path_funlinkat);
ATF_TP_ADD_TC(tp, path_io); ATF_TP_ADD_TC(tp, path_io);
ATF_TP_ADD_TC(tp, path_ioctl); ATF_TP_ADD_TC(tp, path_ioctl);
ATF_TP_ADD_TC(tp, path_lock); ATF_TP_ADD_TC(tp, path_lock);
ATF_TP_ADD_TC(tp, path_rights); ATF_TP_ADD_TC(tp, path_rights);
ATF_TP_ADD_TC(tp, path_unix);
return (atf_no_error()); return (atf_no_error());
} }