From 7a7077c028cf38d6f086fdf15b487a0ad276c621 Mon Sep 17 00:00:00 2001 From: anton Date: Mon, 3 Jun 2024 08:02:22 +0000 Subject: [PATCH] Pledge violation messages are no longer accessible through dmesg since 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 | 4 +- regress/sys/kern/pledge/generic/manager.c | 96 ++++++++++---------- regress/sys/kern/pledge/generic/pty.c | 103 ++++++++++++++++++++++ regress/sys/kern/pledge/generic/pty.h | 22 +++++ 4 files changed, 172 insertions(+), 53 deletions(-) create mode 100644 regress/sys/kern/pledge/generic/pty.c create mode 100644 regress/sys/kern/pledge/generic/pty.h diff --git a/regress/sys/kern/pledge/generic/Makefile b/regress/sys/kern/pledge/generic/Makefile index 6f7deff5788..0db29603482 100644 --- a/regress/sys/kern/pledge/generic/Makefile +++ b/regress/sys/kern/pledge/generic/Makefile @@ -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 diff --git a/regress/sys/kern/pledge/generic/manager.c b/regress/sys/kern/pledge/generic/manager.c index 207923bc24f..5ed58fb00b3 100644 --- a/regress/sys/kern/pledge/generic/manager.c +++ b/regress/sys/kern/pledge/generic/manager.c @@ -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 * @@ -32,6 +32,7 @@ #include #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(®ex, 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(®ex, 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 index 00000000000..3651713b640 --- /dev/null +++ b/regress/sys/kern/pledge/generic/pty.c @@ -0,0 +1,103 @@ +/* $OpenBSD: pty.c,v 1.1 2024/06/03 08:02:22 anton Exp $ */ + +#include + +#include +#include +#include +#include + +#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 index 00000000000..6776f4869c9 --- /dev/null +++ b/regress/sys/kern/pledge/generic/pty.h @@ -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; +} -- 2.20.1