summaryrefslogtreecommitdiff
path: root/repo/doas
diff options
context:
space:
mode:
Diffstat (limited to 'repo/doas')
-rw-r--r--repo/doas/configuration-directory.patch509
-rwxr-xr-xrepo/doas/doas.post-install32
-rwxr-xr-xrepo/doas/doas.post-upgrade37
-rw-r--r--repo/doas/doas.xibuild44
-rw-r--r--repo/doas/manpage-example-path.patch16
5 files changed, 638 insertions, 0 deletions
diff --git a/repo/doas/configuration-directory.patch b/repo/doas/configuration-directory.patch
new file mode 100644
index 0000000..78e6fc3
--- /dev/null
+++ b/repo/doas/configuration-directory.patch
@@ -0,0 +1,509 @@
+From 7de1d454bda06d68a04f4f2e48099398a7711ae9 Mon Sep 17 00:00:00 2001
+From: Ariadne Conill <ariadne@dereferenced.org>
+Date: Wed, 4 Aug 2021 04:47:04 -0600
+Subject: [PATCH 1/8] add --with-confdir feature
+
+This adds support for an /etc/doas.d configuration directory as discussed in #61. It is disabled by default.
+---
+ README.md | 9 +++++++
+ configure | 8 +++++++
+ doas.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ parse.y | 3 ++-
+ 4 files changed, 91 insertions(+), 1 deletion(-)
+
+diff --git a/README.md b/README.md
+index f15610c..f967eca 100644
+--- a/README.md
++++ b/README.md
+@@ -61,3 +61,12 @@ similar to sudo.
+
+ See the comment block in `timestamp.c` for an in-depth description on how
+ timestamps are created and checked to be as safe as possible.
++
++### `--with-doas-confdir`
++
++An optional feature can be enabled which will result in `doas` reading configuration
++snippets from `/etc/doas.d`. These configuration snippets have the same requirements
++as `/etc/doas.conf` (owned by root, not world-writable).
++
++If this feature is enabled, only the `/etc/doas.d` directory is read, and the historical
++`/etc/doas.conf` file is ignored.
+\ No newline at end of file
+diff --git a/configure b/configure
+index 1f92f01..a3078dc 100755
+--- a/configure
++++ b/configure
+@@ -27,6 +27,7 @@ usage: configure [options]
+ --without-shadow disable shadow support
+
+ --with-timestamp enable timestamp support
++ --with-doas-confdir enable configuration directory support
+
+ --uid-max=NUM set UID_MAX (default 65535)
+ --gid-max=NUM set GID_MAX (default 65535)
+@@ -38,6 +39,7 @@ EOF
+
+ # defaults
+ WITHOUT_TIMESTAMP=yes
++WITHOUT_CONFDIR=yes
+ UID_MAX=65535
+ GID_MAX=65535
+
+@@ -56,6 +58,8 @@ for x; do
+ --target) TARGET=$var ;;
+ --enable-debug) DEBUG=yes ;;
+ --enable-static) BUILD_STATIC=yes ;;
++ --with-doas-confdir) WITHOUT_CONFDIR= ;;
++ --without-doas-confdir) WITHOUT_CONFDIR=yes ;;
+ --with-pam) WITHOUT_PAM=; WITHOUT_SHADOW=yes ;;
+ --with-shadow) WITHOUT_SHADOW=; WITHOUT_PAM=yes ;;
+ --without-pam) WITHOUT_PAM=yes ;;
+@@ -558,4 +562,8 @@ fi
+
+ printf '#define DOAS_CONF "%s/doas.conf"\n' "${SYSCONFDIR}" >>$CONFIG_H
+
++if [ -z "$WITHOUT_CONFDIR" ]; then
++ printf '#define DOAS_CONFDIR "%s/doas.d"\n' "${SYSCONFDIR}" >>$CONFIG_H
++fi
++
+ printf '\n#endif /* CONFIG_H */\n' >>$CONFIG_H
+diff --git a/doas.c b/doas.c
+index ac3a42a..58701b7 100644
+--- a/doas.c
++++ b/doas.c
+@@ -35,6 +35,7 @@
+ #include <syslog.h>
+ #include <errno.h>
+ #include <fcntl.h>
++#include <dirent.h>
+
+ #include "openbsd.h"
+ #include "doas.h"
+@@ -155,6 +156,7 @@ permit(uid_t uid, gid_t *groups, int ngroups, const struct rule **lastr,
+ static void
+ parseconfig(const char *filename, int checkperms)
+ {
++ extern const char *yyfn;
+ extern FILE *yyfp;
+ extern int yyparse(void);
+ struct stat sb;
+@@ -164,6 +166,8 @@ parseconfig(const char *filename, int checkperms)
+ err(1, checkperms ? "doas is not enabled, %s" :
+ "could not open config file %s", filename);
+
++ yyfn = filename;
++
+ if (checkperms) {
+ if (fstat(fileno(yyfp), &sb) != 0)
+ err(1, "fstat(\"%s\")", filename);
+@@ -174,11 +178,67 @@ parseconfig(const char *filename, int checkperms)
+ }
+
+ yyparse();
++ yyfn = NULL;
++
+ fclose(yyfp);
+ if (parse_errors)
+ exit(1);
+ }
+
++#ifdef DOAS_CONFDIR
++static int
++isconfdir(const char *dirpath)
++{
++ struct stat sb;
++
++ if (lstat(dirpath, &sb) != 0)
++ err(1, "lstat(\"%s\")", dirpath);
++
++ if ((sb.st_mode & (S_IFMT)) == S_IFDIR)
++ return 1;
++
++ errno = ENOTDIR;
++ return 0;
++}
++
++static void
++parseconfdir(const char *dirpath, int checkperms)
++{
++ struct dirent **dirent_table;
++ size_t i, dirent_count;
++ char pathbuf[PATH_MAX];
++
++ if (!isconfdir(dirpath))
++ err(1, checkperms ? "doas is not enabled, %s" :
++ "could not open config directory %s", dirpath);
++
++ dirent_count = scandir(dirpath, &dirent_table, NULL, alphasort);
++
++ for (i = 0; i < dirent_count; i++)
++ {
++ struct stat sb;
++ size_t pathlen;
++
++ pathlen = snprintf(pathbuf, sizeof pathbuf, "%s/%s", dirpath, dirent_table[i]->d_name);
++ free(dirent_table[i]);
++
++ /* make sure path ends in .conf */
++ if (strcmp(pathbuf + (pathlen - 5), ".conf"))
++ continue;
++
++ if (stat(pathbuf, &sb) != 0)
++ err(1, "stat(\"%s\")", pathbuf);
++
++ if ((sb.st_mode & (S_IFMT)) != S_IFREG)
++ continue;
++
++ parseconfig(pathbuf, checkperms);
++ }
++
++ free(dirent_table);
++}
++#endif
++
+ static void __dead
+ checkconfig(const char *confpath, int argc, char **argv,
+ uid_t uid, gid_t *groups, int ngroups, uid_t target)
+@@ -188,7 +248,13 @@ checkconfig(const char *confpath, int argc, char **argv,
+ if (setresuid(uid, uid, uid) != 0)
+ err(1, "setresuid");
+
++#ifdef DOAS_CONFDIR
++ if (isconfdir(confpath))
++ parseconfdir(confpath, 0);
++ else
++#else
+ parseconfig(confpath, 0);
++#endif
+ if (!argc)
+ exit(0);
+
+@@ -330,7 +396,13 @@ main(int argc, char **argv)
+ if (geteuid())
+ errx(1, "not installed setuid");
+
++#ifdef DOAS_CONFDIR
++ if (isconfdir(DOAS_CONFDIR))
++ parseconfdir(DOAS_CONFDIR, 1);
++ else
++#else
+ parseconfig(DOAS_CONF, 1);
++#endif
+
+ /* cmdline is used only for logging, no need to abort on truncate */
+ (void)strlcpy(cmdline, argv[0], sizeof(cmdline));
+diff --git a/parse.y b/parse.y
+index 388c2a5..c6d7ebf 100644
+--- a/parse.y
++++ b/parse.y
+@@ -49,6 +49,7 @@ typedef struct {
+ } yystype;
+ #define YYSTYPE yystype
+
++const char *yyfn;
+ FILE *yyfp;
+
+ struct rule **rules;
+@@ -203,7 +204,7 @@ yyerror(const char *fmt, ...)
+ va_start(va, fmt);
+ vfprintf(stderr, fmt, va);
+ va_end(va);
+- fprintf(stderr, " at line %d\n", yylval.lineno + 1);
++ fprintf(stderr, " at %s, line %d\n", yyfn, yylval.lineno + 1);
+ parse_errors++;
+ }
+
+
+From 046ff34408ea8bf2cafc079bd71a126aa009b005 Mon Sep 17 00:00:00 2001
+From: Ariadne Conill <ariadne@dereferenced.org>
+Date: Wed, 4 Aug 2021 09:20:35 -0600
+Subject: [PATCH 2/8] gracefully handle ENOENT in isconfdir()
+
+---
+ doas.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/doas.c b/doas.c
+index 58701b7..4c0cafe 100644
+--- a/doas.c
++++ b/doas.c
+@@ -191,8 +191,13 @@ isconfdir(const char *dirpath)
+ {
+ struct stat sb;
+
+- if (lstat(dirpath, &sb) != 0)
+- err(1, "lstat(\"%s\")", dirpath);
++ if (lstat(dirpath, &sb) != 0) {
++ if (errno != ENOENT)
++ err(1, "lstat(\"%s\")", dirpath);
++
++ errno = ENOTDIR;
++ return 0;
++ }
+
+ if ((sb.st_mode & (S_IFMT)) == S_IFDIR)
+ return 1;
+
+From 6e76fb04ac637a1001ba201559f28279e3abe738 Mon Sep 17 00:00:00 2001
+From: Ariadne Conill <ariadne@dereferenced.org>
+Date: Wed, 4 Aug 2021 09:31:49 -0600
+Subject: [PATCH 3/8] ensure pathlen - 5 is always non-zero
+
+---
+ doas.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/doas.c b/doas.c
+index 4c0cafe..f827fcd 100644
+--- a/doas.c
++++ b/doas.c
+@@ -228,6 +228,9 @@ parseconfdir(const char *dirpath, int checkperms)
+ free(dirent_table[i]);
+
+ /* make sure path ends in .conf */
++ if (pathlen < 6)
++ continue;
++
+ if (strcmp(pathbuf + (pathlen - 5), ".conf"))
+ continue;
+
+
+From cac56ea61e16d0ccb91100164a61e9f7215604e5 Mon Sep 17 00:00:00 2001
+From: Ariadne Conill <ariadne@dereferenced.org>
+Date: Wed, 4 Aug 2021 10:17:35 -0600
+Subject: [PATCH 4/8] bail if dirent_count < 0
+
+---
+ doas.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/doas.c b/doas.c
+index f827fcd..6e308c8 100644
+--- a/doas.c
++++ b/doas.c
+@@ -210,7 +210,7 @@ static void
+ parseconfdir(const char *dirpath, int checkperms)
+ {
+ struct dirent **dirent_table;
+- size_t i, dirent_count;
++ int i, dirent_count;
+ char pathbuf[PATH_MAX];
+
+ if (!isconfdir(dirpath))
+@@ -218,6 +218,9 @@ parseconfdir(const char *dirpath, int checkperms)
+ "could not open config directory %s", dirpath);
+
+ dirent_count = scandir(dirpath, &dirent_table, NULL, alphasort);
++ if (dirent_count < 0)
++ err(1, checkperms ? "doas is not enabled, %s" :
++ "could not open config directory %s", dirpath);
+
+ for (i = 0; i < dirent_count; i++)
+ {
+
+From 8d224060adbdb1dececeb02660df8693f7c54a40 Mon Sep 17 00:00:00 2001
+From: Ariadne Conill <ariadne@dereferenced.org>
+Date: Wed, 4 Aug 2021 10:20:33 -0600
+Subject: [PATCH 5/8] error out if no matching configuration files are found in
+ the configuration directory
+
+---
+ doas.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/doas.c b/doas.c
+index 6e308c8..cdfa3ea 100644
+--- a/doas.c
++++ b/doas.c
+@@ -210,7 +210,7 @@ static void
+ parseconfdir(const char *dirpath, int checkperms)
+ {
+ struct dirent **dirent_table;
+- int i, dirent_count;
++ int i, m, dirent_count;
+ char pathbuf[PATH_MAX];
+
+ if (!isconfdir(dirpath))
+@@ -222,7 +222,7 @@ parseconfdir(const char *dirpath, int checkperms)
+ err(1, checkperms ? "doas is not enabled, %s" :
+ "could not open config directory %s", dirpath);
+
+- for (i = 0; i < dirent_count; i++)
++ for (i = 0, m = 0; i < dirent_count; i++)
+ {
+ struct stat sb;
+ size_t pathlen;
+@@ -244,9 +244,16 @@ parseconfdir(const char *dirpath, int checkperms)
+ continue;
+
+ parseconfig(pathbuf, checkperms);
++ m++;
+ }
+
+ free(dirent_table);
++
++ if (!m) {
++ fprintf(stderr, "doas is not enabled, %s: no matching configuration files found\n",
++ dirpath);
++ exit(1);
++ }
+ }
+ #endif
+
+
+From 35c3e69fa52157683b8ae6fe040367390aa63bb6 Mon Sep 17 00:00:00 2001
+From: Ariadne Conill <ariadne@dereferenced.org>
+Date: Wed, 4 Aug 2021 10:34:28 -0600
+Subject: [PATCH 6/8] use errx instead of fprintf(stderr)
+
+---
+ doas.c | 7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+diff --git a/doas.c b/doas.c
+index cdfa3ea..b50138a 100644
+--- a/doas.c
++++ b/doas.c
+@@ -249,11 +249,8 @@ parseconfdir(const char *dirpath, int checkperms)
+
+ free(dirent_table);
+
+- if (!m) {
+- fprintf(stderr, "doas is not enabled, %s: no matching configuration files found\n",
+- dirpath);
+- exit(1);
+- }
++ if (!m)
++ errx(1, "doas is not enabled, %s: no matching configuration files found\n", dirpath);
+ }
+ #endif
+
+
+From c9ff0fcdc0253679a0348995c36f89edc8d73a5b Mon Sep 17 00:00:00 2001
+From: Ariadne Conill <ariadne@dereferenced.org>
+Date: Wed, 4 Aug 2021 16:50:58 -0600
+Subject: [PATCH 7/8] fix up the ifndef DOAS_CONFDIR branch
+
+---
+ doas.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/doas.c b/doas.c
+index b50138a..d77186b 100644
+--- a/doas.c
++++ b/doas.c
+@@ -267,9 +267,8 @@ checkconfig(const char *confpath, int argc, char **argv,
+ if (isconfdir(confpath))
+ parseconfdir(confpath, 0);
+ else
+-#else
+- parseconfig(confpath, 0);
+ #endif
++ parseconfig(confpath, 0);
+ if (!argc)
+ exit(0);
+
+@@ -415,9 +414,8 @@ main(int argc, char **argv)
+ if (isconfdir(DOAS_CONFDIR))
+ parseconfdir(DOAS_CONFDIR, 1);
+ else
+-#else
+- parseconfig(DOAS_CONF, 1);
+ #endif
++ parseconfig(DOAS_CONF, 1);
+
+ /* cmdline is used only for logging, no need to abort on truncate */
+ (void)strlcpy(cmdline, argv[0], sizeof(cmdline));
+
+From 9fe4df5f004435fa0b092dc15a3c5ab09090f45d Mon Sep 17 00:00:00 2001
+From: Ariadne Conill <ariadne@dereferenced.org>
+Date: Fri, 3 Sep 2021 11:59:12 -0600
+Subject: [PATCH 8/8] add manpage for doas.d(5)
+
+---
+ GNUmakefile | 1 +
+ doas.conf.5 | 1 +
+ doas.d.5 | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 52 insertions(+)
+ create mode 100644 doas.d.5
+
+diff --git a/GNUmakefile b/GNUmakefile
+index 2eef88e..423731c 100644
+--- a/GNUmakefile
++++ b/GNUmakefile
+@@ -24,6 +24,7 @@ install: ${PROG} ${MAN}
+ chmod ${BINMODE} ${DESTDIR}${BINDIR}/${PROG}
+ cp -f doas.1 ${DESTDIR}${MANDIR}/man1
+ cp -f doas.conf.5 ${DESTDIR}${MANDIR}/man5
++ cp -f doas.d.5 ${DESTDIR}${MANDIR}/man5
+
+ uninstall:
+ rm -f ${DESTDIR}${BINDIR}/${PROG}
+diff --git a/doas.conf.5 b/doas.conf.5
+index e98bfbe..e90d512 100644
+--- a/doas.conf.5
++++ b/doas.conf.5
+@@ -143,6 +143,7 @@ permit nopass keepenv setenv { PATH } root as root
+ .Ed
+ .Sh SEE ALSO
+ .Xr doas 1 ,
++.Xr doas.d 5 ,
+ .Xr syslogd 8
+ .Sh HISTORY
+ The
+diff --git a/doas.d.5 b/doas.d.5
+new file mode 100644
+index 0000000..8f5f96a
+--- /dev/null
++++ b/doas.d.5
+@@ -0,0 +1,50 @@
++.\"Copyright (c) 2021 Ariadne Conill <ariadne@dereferenced.org>
++.\"
++.\"Permission to use, copy, modify, and distribute this software for any
++.\"purpose with or without fee is hereby granted, provided that the above
++.\"copyright notice and this permission notice appear in all copies.
++.\"
++.\"THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++.\"WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++.\"MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++.\"ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++.\"WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++.\"ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++.\"OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++.Dd $Mdocdate: October 9 2020 $
++.Dt DOAS.D 5
++.Os
++.Sh NAME
++.Nm doas.d
++.Nd doas configuration directory
++.Sh DESCRIPTION
++The
++.Xr doas 1
++utility executes commands as other users according to the rules
++configured in either the configuration file or, optionally, the
++configuration directory. The preference to use the configuration
++file or configuration directory is determined at compile time,
++.Xr doas 1
++will only consult one or the other.
++.Pp
++Configuration snippets stored in the configuration directory
++follow the same rules as the classic
++.Xr doas 1
++configuration file, documented in
++.Xr doas.conf 5 .
++They must end with the .conf extension, or they will be ignored.
++.Pp
++These snippets are read in alphabetical order and thus can be
++ordered in the same way as other configuration directories.
++.Sh FILES
++.Bl -tag -width /etc/doas.d -compact
++.It Pa /etc/doas.d
++.Xr doas 1
++configuration directory.
++.Sh SEE ALSO
++.Xr doas 1 ,
++.Xr doas.conf 5
++.Sh HISTORY
++The
++.Nm
++configuration directory first appeared in OpenDoas.
diff --git a/repo/doas/doas.post-install b/repo/doas/doas.post-install
new file mode 100755
index 0000000..65c3cff
--- /dev/null
+++ b/repo/doas/doas.post-install
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+[ -d /etc/doas.d ] || install -d -m 0750 /etc/doas.d
+[ -e /etc/doas.d/doas.conf ] && exit 0
+
+cat << _EOF_ >/etc/doas.d/doas.conf
+# This file is actually located at /etc/doas.d/doas.conf, and reflects
+# the system doas configuration. It may have been migrated from its
+# previous location, /etc/doas.conf, automatically.
+_EOF_
+
+if [ -f /etc/doas.conf ]; then
+ cat /etc/doas.conf >> /etc/doas.d/doas.conf
+ cat << _EOF_ >> /etc/doas.d/doas.conf
+# Please see /usr/share/doc/doas/doas.conf.example in the doas-doc
+# package for configuration examples.
+_EOF_
+
+ # install compatibility symlink
+ rm -f /etc/doas.conf
+ ln -sf /etc/doas.d/doas.conf /etc/doas.conf
+
+ # chmod 600
+ chmod 600 /etc/doas.d/doas.conf
+
+ cat <<- _EOF_ >&2
+ * Your configuration in /etc/doas.conf was migrated to
+ * /etc/doas.d/doas.conf and a symlink was installed in its
+ * place. For more information about the new doas configuration
+ * directory, consult doas.d(5).
+ _EOF_
+fi
diff --git a/repo/doas/doas.post-upgrade b/repo/doas/doas.post-upgrade
new file mode 100755
index 0000000..731b351
--- /dev/null
+++ b/repo/doas/doas.post-upgrade
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+[ -d /etc/doas.d ] || install -d -m 0750 /etc/doas.d
+# fix perms when upgrading from 6.8.1-r6
+if [ -d /etc/doas.d ] && [ "$(stat -c "%a" /etc/doas.d)" = "755" ]; then
+ chmod 0750 /etc/doas.d
+fi
+
+[ -e /etc/doas.d/doas.conf ] && exit 0
+
+cat << _EOF_ >/etc/doas.d/doas.conf
+# This file is actually located at /etc/doas.d/doas.conf, and reflects
+# the system doas configuration. It may have been migrated from its
+# previous location, /etc/doas.conf, automatically.
+_EOF_
+
+if [ -f /etc/doas.conf ]; then
+ cat /etc/doas.conf >> /etc/doas.d/doas.conf
+ cat << _EOF_ >> /etc/doas.d/doas.conf
+# Please see /usr/share/doc/doas/doas.conf.example in the doas-doc
+# package for configuration examples.
+_EOF_
+fi
+
+# install compatibility symlink
+rm -f /etc/doas.conf
+ln -sf /etc/doas.d/doas.conf /etc/doas.conf
+
+# chmod 600
+chmod 600 /etc/doas.d/doas.conf
+
+cat << _EOF_ >&2
+ * Your configuration in /etc/doas.conf was migrated to
+ * /etc/doas.d/doas.conf and a symlink was installed in its
+ * place. For more information about the new doas configuration
+ * directory, consult doas.d(5).
+_EOF_
diff --git a/repo/doas/doas.xibuild b/repo/doas/doas.xibuild
new file mode 100644
index 0000000..3e3b4f8
--- /dev/null
+++ b/repo/doas/doas.xibuild
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+NAME="doas"
+DESC="OpenBSD's temporary privilege escalation tool"
+
+MAKEDEPS="bison"
+
+PKG_VER=6.8.2
+SOURCE="https://github.com/Duncaen/OpenDoas/archive/v$PKG_VER.tar.gz"
+
+ADDITIONAL="
+configuration-directory.patch
+manpage-example-path.patch
+"
+
+prepare () {
+ apply_patches
+}
+
+build() {
+ ./configure \
+ --prefix=/usr \
+ --without-pam \
+ --with-timestamp \
+ --with-doas-confdir
+ make
+}
+
+check() {
+ # doas -v returns 1
+ ./doas -v || test $? = 1
+}
+
+package() {
+ make install DESTDIR="$PKG_DEST"
+ install -d "$PKG_DEST"/usr/share/doc/doas
+ cat > "$PKG_DEST"/usr/share/doc/doas/doas.conf.example <<-EOF
+ # see doas.conf(5) for configuration details
+
+ # Uncomment to allow group "wheel" to become root
+ # permit persist :wheel
+ EOF
+}
+
diff --git a/repo/doas/manpage-example-path.patch b/repo/doas/manpage-example-path.patch
new file mode 100644
index 0000000..31048c7
--- /dev/null
+++ b/repo/doas/manpage-example-path.patch
@@ -0,0 +1,16 @@
+--- OpenDoas-6.8.1.orig/doas.conf.5
++++ OpenDoas-6.8.1/doas.conf.5
+@@ -114,11 +114,11 @@
+ it is not considered a keyword.
+ .El
+ .Sh FILES
+-.Bl -tag -width /etc/examples/doas.conf -compact
++.Bl -tag -width /usr/share/doc/doas/doas.conf.example -compact
+ .It Pa /etc/doas.conf
+ .Xr doas 1
+ configuration file.
+-.It Pa /etc/examples/doas.conf
++.It Pa /usr/share/doc/doas/doas.conf.example
+ Example configuration file.
+ .El
+ .Sh EXAMPLES