Pledge violation messages are no longer accessible through dmesg since
authoranton <anton@openbsd.org>
Mon, 3 Jun 2024 08:02:22 +0000 (08:02 +0000)
committeranton <anton@openbsd.org>
Mon, 3 Jun 2024 08:02:22 +0000 (08:02 +0000)
the switch to uprintf. Attach a pseudo terminal in pledge regress in order to
observe the syscall number that caused the pledge violation, shrug.

regress/sys/kern/pledge/generic/Makefile
regress/sys/kern/pledge/generic/manager.c
regress/sys/kern/pledge/generic/pty.c [new file with mode: 0644]
regress/sys/kern/pledge/generic/pty.h [new file with mode: 0644]

index 6f7deff..0db2960 100644 (file)
@@ -1,6 +1,6 @@
-#      $OpenBSD: Makefile,v 1.10 2020/04/01 15:26:53 claudio Exp $
+#      $OpenBSD: Makefile,v 1.11 2024/06/03 08:02:22 anton Exp $
 PROG=  generic
-SRCS=  main.c manager.c test_stdio.c test_tty.c
+SRCS=  main.c manager.c test_stdio.c test_tty.c pty.c
 NOMAN= yes
 
 LDADD+=                -lutil
index 207923b..5ed58fb 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: manager.c,v 1.8 2024/04/26 04:44:43 jsg Exp $ */
+/*     $OpenBSD: manager.c,v 1.9 2024/06/03 08:02:22 anton Exp $ */
 /*
  * Copyright (c) 2015 Sebastien Marie <semarie@openbsd.org>
  *
@@ -32,6 +32,7 @@
 #include <unistd.h>
 
 #include "manager.h"
+#include "pty.h"
 
 extern char *__progname;
 
@@ -89,20 +90,18 @@ clear_coredump(int *ret, const char *test_name)
 
 
 static int
-grab_syscall(pid_t pid)
+grab_syscall(pid_t pid, char *output)
 {
        int              ret = -1;
        char            *pattern;
        regex_t          regex;
        regmatch_t       matches[2];
-       FILE            *fd;
-       char             line[1024];
        int              error;
        const char      *errstr;
 
        /* build searched string */
        error = asprintf(&pattern,
-           "^%s\\[%d\\]: pledge \"[a-z]+\", syscall ([0-9]+)\n?$",
+           "%s\\[%d\\]: pledge \"[a-z]+\", syscall ([0-9]+)",
            __progname, pid);
        if (error <= 0) {
                warn("asprintf pattern");
@@ -119,56 +118,28 @@ grab_syscall(pid_t pid)
                goto out;
        }
 
-       /* call dmesg */
-       if ((fd = popen("/sbin/dmesg", "r")) == NULL) {
-               warn("popen /sbin/dmesg");
+       /* search the string */
+       error = regexec(&regex, output, 2, matches, 0);
+       if (error == REG_NOMATCH) {
+               ret = 0;
                goto out;
        }
-
-       /* search the string */
-       while (1) {
-               /* read a line */
-               fgets(line, sizeof(line), fd);
-
-               /* error checking */
-               if (ferror(fd)) {
-                       ret = -1;
-                       goto out;
-               }
-
-               /* quit */
-               if (feof(fd))
-                       break;
-
-               /* check if found */
-               error = regexec(&regex, line, 2, matches, 0);
-               if (error == REG_NOMATCH)
-                       continue;
-               if (error) {
-                       warnx("regexec pattern=%s line=%s error=%d",
-                           pattern, line, error);
-                       ret = -1;
-                       goto out;
-               }
-
-               /* convert it */
-               line[matches[1].rm_eo] = '\0';
-               ret = strtonum(&line[matches[1].rm_so], 0, 255, &errstr);
-               if (errstr) {
-                       warnx("strtonum: number=%s error=%s",
-                           &line[matches[1].rm_so], errstr);
-                       ret = -1;
-                       goto out;
-               }
+       if (error) {
+               warnx("regexec pattern=%s output=%s error=%d",
+                   pattern, output, error);
+               ret = -1;
+               goto out;
        }
 
-       /* cleanup */
-       if (pclose(fd) == -1)
+       /* convert it */
+       output[matches[1].rm_eo] = '\0';
+       ret = strtonum(&output[matches[1].rm_so], 0, 255, &errstr);
+       if (errstr) {
+               warnx("strtonum: number=%s error=%s",
+                   &output[matches[1].rm_so], errstr);
+               ret = -1;
                goto out;
-
-       /* not found */
-       if (ret == -1)
-               ret = 0;
+       }
 
 out:
        free(pattern);
@@ -198,6 +169,7 @@ void
 _start_test(int *ret, const char *test_name, const char *request,
     void (*test_func)(void))
 {
+       struct pty pty = {0};
        int fildes[2];
        pid_t pid;
        int status;
@@ -228,6 +200,11 @@ _start_test(int *ret, const char *test_name, const char *request,
                return;
        }
 
+       if (pty_open(&pty)) {
+               *ret = EXIT_FAILURE;
+               return;
+       }
+
        /* fork and launch the test */
        switch (pid = fork()) {
        case -1:
@@ -245,9 +222,19 @@ _start_test(int *ret, const char *test_name, const char *request,
                        if (errno != EINTR)
                                err(errno, "dup2");
 
+               if (pty_detach(&pty)) {
+                       *ret = EXIT_FAILURE;
+                       return;
+               }
+
                /* create a new session (for kill) */
                setsid();
 
+               if (pty_attach(&pty)) {
+                       *ret = EXIT_FAILURE;
+                       return;
+               }
+
                /* set pledge policy */
                if (request && pledge(request, NULL) != 0)
                        err(errno, "pledge");
@@ -263,6 +250,11 @@ _start_test(int *ret, const char *test_name, const char *request,
                /* NOTREACHED */
        }
 
+       if (pty_drain(&pty)) {
+               *ret = EXIT_FAILURE;
+               return;
+       }
+
        /* copy pipe to output */
        (void)close(fildes[1]);
        if (drainfd(fildes[0], STDOUT_FILENO) != 0) {
@@ -331,7 +323,7 @@ _start_test(int *ret, const char *test_name, const char *request,
 
                /* grab pledged syscall from dmesg */
                if (signal == SIGKILL || signal == SIGABRT) {
-                       int syscall = grab_syscall(pid);
+                       int syscall = grab_syscall(pid, pty_buffer(&pty));
                        switch (syscall) {
                        case -1:        /* error */
                                warn("test(%s): grab_syscall pid=%d", test_name,
@@ -352,5 +344,7 @@ _start_test(int *ret, const char *test_name, const char *request,
        if (WIFSTOPPED(status))
                printf(" stop=%d", WSTOPSIG(status));
 
+       pty_close(&pty);
+
        printf("\n");
 }
diff --git a/regress/sys/kern/pledge/generic/pty.c b/regress/sys/kern/pledge/generic/pty.c
new file mode 100644 (file)
index 0000000..3651713
--- /dev/null
@@ -0,0 +1,103 @@
+/*     $OpenBSD: pty.c,v 1.1 2024/06/03 08:02:22 anton Exp $   */
+
+#include <sys/ioctl.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "pty.h"
+
+int
+pty_open(struct pty *pty)
+{
+       int master, slave;
+
+       master = posix_openpt(O_RDWR);
+       if (master == -1) {
+               warn("posix_openpt");
+               return 1;
+       }
+       if (grantpt(master) == -1) {
+               warn("grantpt");
+               return 1;
+       }
+       if (unlockpt(master) == -1) {
+               warn("unlockpt");
+               return 1;
+       }
+
+       slave = open(ptsname(master), O_RDWR);
+       if (slave == -1) {
+               warn("%s", ptsname(master));
+               return 1;
+       }
+
+       pty->master = master;
+       pty->slave = slave;
+       return 0;
+}
+
+void
+pty_close(struct pty *pty)
+{
+       close(pty->slave);
+       close(pty->master);
+}
+
+/*
+ * Disconnect the controlling tty, if present.
+ */
+int
+pty_detach(struct pty *pty)
+{
+       int fd;
+
+       fd = open("/dev/tty", O_RDWR | O_NOCTTY);
+       if (fd >= 0) {
+               (void)ioctl(fd, TIOCNOTTY, NULL);
+               close(fd);
+       }
+       return 0;
+}
+
+/*
+ * Connect the slave as the controlling tty.
+ */
+int
+pty_attach(struct pty *pty)
+{
+       if (ioctl(pty->slave, TIOCSCTTY, NULL) == -1) {
+               warn("TIOCSCTTY");
+               return 1;
+       }
+       return 0;
+}
+
+int
+pty_drain(struct pty *pty)
+{
+       for (;;) {
+               char *buf = &pty->buf.storage[pty->buf.len];
+               size_t bufsize = sizeof(pty->buf.storage) - pty->buf.len;
+               ssize_t n;
+
+               n = read(pty->master, buf, bufsize);
+               if (n == -1) {
+                       warn("read");
+                       return 1;
+               }
+               if (n == 0)
+                       break;
+
+               /* Ensure space for NUL-terminator. */
+               if ((size_t)n >= bufsize) {
+                       warnx("pty buffer too small");
+                       return 1;
+               }
+               pty->buf.len += n;
+       }
+
+       return 0;
+}
diff --git a/regress/sys/kern/pledge/generic/pty.h b/regress/sys/kern/pledge/generic/pty.h
new file mode 100644 (file)
index 0000000..6776f48
--- /dev/null
@@ -0,0 +1,22 @@
+/*     $OpenBSD: pty.h,v 1.1 2024/06/03 08:02:22 anton Exp $   */
+
+struct pty {
+       struct {
+               char    storage[1024];
+               size_t  len;
+       } buf;
+       int     master;
+       int     slave;
+};
+
+int    pty_open(struct pty *);
+void   pty_close(struct pty *);
+int    pty_detach(struct pty *);
+int    pty_attach(struct pty *);
+int    pty_drain(struct pty *pty);
+
+static inline char *
+pty_buffer(struct pty *pty)
+{
+       return pty->buf.storage;
+}