Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F162637797
D57147.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D57147.diff
View Options
diff --git a/tests/sys/kern/Makefile b/tests/sys/kern/Makefile
--- a/tests/sys/kern/Makefile
+++ b/tests/sys/kern/Makefile
@@ -95,7 +95,7 @@
LIBADD.aslr+= util
LIBADD.copy_file_range+= md
LIBADD.jail_lookup_root+= jail util
-LIBADD.jaildesc+= pthread
+LIBADD.jaildesc+= kvm pthread
LIBADD.ssl_sendfile+= pthread crypto ssl
CFLAGS.sys_getrandom+= -I${SRCTOP}/sys/contrib/zstd/lib
LIBADD.sys_getrandom+= zstd
diff --git a/tests/sys/kern/jaildesc.c b/tests/sys/kern/jaildesc.c
--- a/tests/sys/kern/jaildesc.c
+++ b/tests/sys/kern/jaildesc.c
@@ -6,16 +6,56 @@
#include <sys/param.h>
#include <sys/jail.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
#include <sys/uio.h>
+#include <sys/user.h>
#include <atf-c.h>
#include <errno.h>
+#include <fcntl.h>
#include <poll.h>
#include <pthread.h>
#include <pwd.h>
+#include <signal.h>
#include <string.h>
#include <unistd.h>
+#include <kvm.h>
+
+/*
+ * Block until a thread in the specified process is sleeping in the specified
+ * wait message.
+ */
+static void
+wait_for_naptime(pid_t pid, const char *wmesg)
+{
+ kvm_t *kd;
+ int count;
+
+ kd = kvm_openfiles(NULL, "/dev/null", NULL, O_RDONLY, NULL);
+ ATF_REQUIRE(kd != NULL);
+ for (;;) {
+ struct kinfo_proc *kip;
+ int i;
+
+ usleep(1000);
+ kip = kvm_getprocs(kd, KERN_PROC_PID | KERN_PROC_INC_THREAD,
+ pid, &count);
+ ATF_REQUIRE(kip != NULL);
+ for (i = 0; i < count; i++) {
+ ATF_REQUIRE(kip[i].ki_stat != SZOMB);
+ if (kip[i].ki_stat == SSLEEP &&
+ strcmp(kip[i].ki_wmesg, wmesg) == 0)
+ break;
+ }
+ if (i < count)
+ break;
+ }
+
+ kvm_close(kd);
+}
+
/*
* Create a persistent jail and return an owning descriptor for it.
* The jail is removed when the returned descriptor is closed.
@@ -191,11 +231,175 @@
ATF_REQUIRE_MSG(close(owning_jd) == 0, "close: %s", strerror(errno));
}
+/*
+ * Verify that a process inside a jail cannot obtain a jail descriptor for
+ * its own jail.
+ */
+ATF_TC(curjail_get);
+ATF_TC_HEAD(curjail_get, tc)
+{
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+ATF_TC_BODY(curjail_get, tc)
+{
+ char namebuf[MAXHOSTNAMELEN];
+ struct iovec iov[4];
+ int desc, error, jid, n;
+
+ (void)create_jail("jaildesc_get_desc_current_jail");
+
+ strlcpy(namebuf, "jaildesc_get_desc_current_jail", sizeof(namebuf));
+ jid = -1;
+ n = 0;
+ iov[n].iov_base = __DECONST(void *, "name");
+ iov[n++].iov_len = sizeof("name");
+ iov[n].iov_base = namebuf;
+ iov[n++].iov_len = strlen(namebuf) + 1;
+ jid = jail_get(iov, n, 0);
+ ATF_REQUIRE_MSG(jid >= 0, "jail_get: %s", strerror(errno));
+
+ error = jail_attach(jid);
+ ATF_REQUIRE_MSG(error == 0, "jail_attach: %s", strerror(errno));
+
+ /*
+ * Now that we are inside the jail, verify that we cannot obtain a
+ * descriptor for it.
+ */
+ strlcpy(namebuf, "jaildesc_get_desc_current_jail", sizeof(namebuf));
+ desc = -1;
+ n = 0;
+ iov[n].iov_base = __DECONST(void *, "name");
+ iov[n++].iov_len = sizeof("name");
+ iov[n].iov_base = namebuf;
+ iov[n++].iov_len = strlen(namebuf) + 1;
+ iov[n].iov_base = __DECONST(void *, "desc");
+ iov[n++].iov_len = sizeof("desc");
+ iov[n].iov_base = &desc;
+ iov[n++].iov_len = sizeof(desc);
+ ATF_REQUIRE_MSG(jail_get(iov, n, JAIL_GET_DESC) == -1,
+ "jail_get succeeded unexpectedly");
+ ATF_REQUIRE_MSG(jail_get(iov, n, JAIL_OWN_DESC) == -1,
+ "jail_get succeeded unexpectedly");
+}
+
+static void
+nop(int signum __unused)
+{
+}
+
+/*
+ * Close an owning descriptor while in the corresponding jail.
+ */
+ATF_TC(self_destruct);
+ATF_TC_HEAD(self_destruct, tc)
+{
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+ATF_TC_BODY(self_destruct, tc)
+{
+ int error, jd, status;
+ pid_t pid;
+
+ jd = create_jail("jaildesc_self_destruct");
+
+ pid = fork();
+ ATF_REQUIRE_MSG(pid >= 0, "fork: %s", strerror(errno));
+ if (pid == 0) {
+ struct sigaction sa;
+
+ error = jail_attach_jd(jd);
+ if (error != 0)
+ _exit(1);
+
+ sa.sa_handler = nop;
+ sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+ error = sigaction(SIGALRM, &sa, NULL);
+ if (error != 0)
+ _exit(2);
+
+ pause();
+ close(jd);
+ /* NOTREACHED? */
+ _exit(3);
+ }
+
+ wait_for_naptime(pid, "sigsusp");
+
+ error = close(jd);
+ ATF_REQUIRE_MSG(error == 0, "close: %s", strerror(errno));
+
+ error = kill(pid, SIGALRM);
+ ATF_REQUIRE_MSG(error == 0, "kill: %s", strerror(errno));
+
+ pid = waitpid(pid, &status, 0);
+ ATF_REQUIRE_MSG(pid >= 0, "waitpid: %s", strerror(errno));
+ ATF_REQUIRE(WIFSIGNALED(status));
+ ATF_REQUIRE_EQ(WTERMSIG(status), SIGKILL);
+}
+
+/*
+ * Try to get an fd for a non-existent jail.
+ */
+ATF_TC(at_desc_bad_fd);
+ATF_TC_HEAD(at_desc_bad_fd, tc)
+{
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+ATF_TC_BODY(at_desc_bad_fd, tc)
+{
+ int jd, status;
+ pid_t pid;
+
+ jd = create_jail("jaildesc_at_desc_bad_fd");
+
+ pid = fork();
+ ATF_REQUIRE_MSG(pid >= 0, "fork: %s", strerror(errno));
+ if (pid == 0) {
+ struct iovec iov[4];
+ char namebuf[MAXHOSTNAMELEN];
+ int desc, i, n;
+
+ if (jail_attach_jd(jd) != 0)
+ _exit(1);
+
+ /* Regression test: loop here to trigger a refcount leak. */
+ for (i = 0; i < 100; i++) {
+ strlcpy(namebuf, "nonexistent", sizeof(namebuf));
+ desc = STDIN_FILENO;
+ n = 0;
+ iov[n].iov_base = __DECONST(void *, "name");
+ iov[n++].iov_len = strlen("name") + 1;
+ iov[n].iov_base = namebuf;
+ iov[n++].iov_len = sizeof(namebuf);
+ iov[n].iov_base = __DECONST(void *, "desc");
+ iov[n++].iov_len = strlen("desc") + 1;
+ iov[n].iov_base = &desc;
+ iov[n++].iov_len = sizeof(desc);
+ if (jail_get(iov, n, JAIL_AT_DESC) != -1)
+ _exit(2);
+ if (errno != EINVAL)
+ _exit(3);
+ }
+ _exit(0);
+ }
+
+ pid = waitpid(pid, &status, 0);
+ ATF_REQUIRE_MSG(pid >= 0, "waitpid: %s", strerror(errno));
+ ATF_REQUIRE_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 0,
+ "child failed with status %d", status);
+
+ ATF_REQUIRE_MSG(close(jd) == 0, "close: %s", strerror(errno));
+}
+
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, poll_close_race);
ATF_TP_ADD_TC(tp, poll_remove_wakeup);
ATF_TP_ADD_TC(tp, poll_close_race_get_desc);
+ ATF_TP_ADD_TC(tp, curjail_get);
+ ATF_TP_ADD_TC(tp, self_destruct);
+ ATF_TP_ADD_TC(tp, at_desc_bad_fd);
return (atf_no_error());
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jul 16, 7:23 AM (11 h, 52 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35129235
Default Alt Text
D57147.diff (6 KB)
Attached To
Mode
D57147: tests/jaildesc: Add a couple more test scenarios
Attached
Detach File
Event Timeline
Log In to Comment