diff --git a/openbsd-pledge-unveil/coreutils-true.c b/openbsd-pledge-unveil/coreutils-true.c
new file mode 100644
index 0000000..3ce0005
--- /dev/null
+++ b/openbsd-pledge-unveil/coreutils-true.c
@@ -0,0 +1,80 @@
+/* Exit with a status code indicating success.
+ Copyright (C) 1999-2025 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see . */
+
+#include
+#include
+#include
+#include "system.h"
+
+/* Act like "true" by default; false.c overrides this. */
+#ifndef EXIT_STATUS
+# define EXIT_STATUS EXIT_SUCCESS
+#endif
+
+#if EXIT_STATUS == EXIT_SUCCESS
+# define PROGRAM_NAME "true"
+#else
+# define PROGRAM_NAME "false"
+#endif
+
+#define AUTHORS proper_name ("Jim Meyering")
+
+void
+usage (int status)
+{
+ printf (_("\
+Usage: %s [ignored command line arguments]\n\
+ or: %s OPTION\n\
+"),
+ program_name, program_name);
+ printf ("%s\n\n",
+ _(EXIT_STATUS == EXIT_SUCCESS
+ ? N_("Exit with a status code indicating success.")
+ : N_("Exit with a status code indicating failure.")));
+ fputs (HELP_OPTION_DESCRIPTION, stdout);
+ fputs (VERSION_OPTION_DESCRIPTION, stdout);
+ printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME);
+ emit_ancillary_info (PROGRAM_NAME);
+ exit (status);
+}
+
+int
+main (int argc, char **argv)
+{
+ /* Recognize --help or --version only if it's the only command-line
+ argument. */
+ if (argc == 2)
+ {
+ initialize_main (&argc, &argv);
+ set_program_name (argv[0]);
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+
+ /* Note true(1) will return EXIT_FAILURE in the
+ edge case where writes fail with GNU specific options. */
+ atexit (close_stdout);
+
+ if (STREQ (argv[1], "--help"))
+ usage (EXIT_STATUS);
+
+ if (STREQ (argv[1], "--version"))
+ version_etc (stdout, PROGRAM_NAME, PACKAGE_NAME, Version, AUTHORS,
+ (char *) nullptr);
+ }
+
+ return EXIT_STATUS;
+}
diff --git a/openbsd-pledge-unveil/doas.c b/openbsd-pledge-unveil/doas.c
new file mode 100644
index 0000000..fe6a816
--- /dev/null
+++ b/openbsd-pledge-unveil/doas.c
@@ -0,0 +1,498 @@
+/* $OpenBSD: doas.c,v 1.99 2024/02/15 18:57:58 tedu Exp $ */
+/*
+ * Copyright (c) 2015 Ted Unangst
+ *
+ * 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.
+ */
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "doas.h"
+
+static void __dead
+usage(void)
+{
+ fprintf(stderr, "usage: doas [-Lns] [-a style] [-C config] [-u user]"
+ " command [arg ...]\n");
+ exit(1);
+}
+
+static int
+parseuid(const char *s, uid_t *uid)
+{
+ struct passwd *pw;
+ const char *errstr;
+
+ if ((pw = getpwnam(s)) != NULL) {
+ *uid = pw->pw_uid;
+ if (*uid == UID_MAX)
+ return -1;
+ return 0;
+ }
+ *uid = strtonum(s, 0, UID_MAX - 1, &errstr);
+ if (errstr)
+ return -1;
+ return 0;
+}
+
+static int
+uidcheck(const char *s, uid_t desired)
+{
+ uid_t uid;
+
+ if (parseuid(s, &uid) != 0)
+ return -1;
+ if (uid != desired)
+ return -1;
+ return 0;
+}
+
+static int
+parsegid(const char *s, gid_t *gid)
+{
+ struct group *gr;
+ const char *errstr;
+
+ if ((gr = getgrnam(s)) != NULL) {
+ *gid = gr->gr_gid;
+ if (*gid == GID_MAX)
+ return -1;
+ return 0;
+ }
+ *gid = strtonum(s, 0, GID_MAX - 1, &errstr);
+ if (errstr)
+ return -1;
+ return 0;
+}
+
+static int
+match(uid_t uid, gid_t *groups, int ngroups, uid_t target, const char *cmd,
+ const char **cmdargs, struct rule *r)
+{
+ int i;
+
+ if (r->ident[0] == ':') {
+ gid_t rgid;
+ if (parsegid(r->ident + 1, &rgid) == -1)
+ return 0;
+ for (i = 0; i < ngroups; i++) {
+ if (rgid == groups[i])
+ break;
+ }
+ if (i == ngroups)
+ return 0;
+ } else {
+ if (uidcheck(r->ident, uid) != 0)
+ return 0;
+ }
+ if (r->target && uidcheck(r->target, target) != 0)
+ return 0;
+ if (r->cmd) {
+ if (strcmp(r->cmd, cmd))
+ return 0;
+ if (r->cmdargs) {
+ /* if arguments were given, they should match explicitly */
+ for (i = 0; r->cmdargs[i]; i++) {
+ if (!cmdargs[i])
+ return 0;
+ if (strcmp(r->cmdargs[i], cmdargs[i]))
+ return 0;
+ }
+ if (cmdargs[i])
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int
+permit(uid_t uid, gid_t *groups, int ngroups, const struct rule **lastr,
+ uid_t target, const char *cmd, const char **cmdargs)
+{
+ size_t i;
+
+ *lastr = NULL;
+ for (i = 0; i < nrules; i++) {
+ if (match(uid, groups, ngroups, target, cmd,
+ cmdargs, rules[i]))
+ *lastr = rules[i];
+ }
+ if (!*lastr)
+ return -1;
+ if ((*lastr)->action == PERMIT)
+ return 0;
+ return -1;
+}
+
+static void
+parseconfig(const char *filename, int checkperms)
+{
+ extern FILE *yyfp;
+ extern int yyparse(void);
+ struct stat sb;
+
+ yyfp = fopen(filename, "r");
+ if (!yyfp)
+ err(1, checkperms ? "doas is not enabled, %s" :
+ "could not open config file %s", filename);
+
+ if (checkperms) {
+ if (fstat(fileno(yyfp), &sb) != 0)
+ err(1, "fstat(\"%s\")", filename);
+ if ((sb.st_mode & (S_IWGRP|S_IWOTH)) != 0)
+ errx(1, "%s is writable by group or other", filename);
+ if (sb.st_uid != 0)
+ errx(1, "%s is not owned by root", filename);
+ }
+
+ yyparse();
+ fclose(yyfp);
+ if (parse_error)
+ exit(1);
+}
+
+static void __dead
+checkconfig(const char *confpath, int argc, char **argv,
+ uid_t uid, gid_t *groups, int ngroups, uid_t target)
+{
+ const struct rule *rule;
+ int rv;
+
+ setresuid(uid, uid, uid);
+ if (pledge("stdio rpath getpw", NULL) == -1)
+ err(1, "pledge");
+ parseconfig(confpath, 0);
+ if (!argc)
+ exit(0);
+ rv = permit(uid, groups, ngroups, &rule, target, argv[0],
+ (const char **)argv + 1);
+ if (rv == 0) {
+ printf("permit%s\n", (rule->options & NOPASS) ? " nopass" : "");
+ exit(0);
+ } else {
+ printf("deny\n");
+ exit(1);
+ }
+}
+
+static int
+authuser_checkpass(char *myname, char *login_style)
+{
+ char *challenge = NULL, *response, rbuf[1024], cbuf[128];
+ auth_session_t *as;
+
+ if (!(as = auth_userchallenge(myname, login_style, "auth-doas",
+ &challenge))) {
+ warnx("Authentication failed");
+ return AUTH_FAILED;
+ }
+ if (!challenge) {
+ char host[HOST_NAME_MAX + 1];
+
+ if (gethostname(host, sizeof(host)))
+ snprintf(host, sizeof(host), "?");
+ snprintf(cbuf, sizeof(cbuf),
+ "\rdoas (%.32s@%.32s) password: ", myname, host);
+ challenge = cbuf;
+ }
+ response = readpassphrase(challenge, rbuf, sizeof(rbuf),
+ RPP_REQUIRE_TTY);
+ if (response == NULL && errno == ENOTTY) {
+ syslog(LOG_AUTHPRIV | LOG_NOTICE,
+ "tty required for %s", myname);
+ errx(1, "a tty is required");
+ }
+ if (!auth_userresponse(as, response, 0)) {
+ explicit_bzero(rbuf, sizeof(rbuf));
+ syslog(LOG_AUTHPRIV | LOG_NOTICE,
+ "failed auth for %s", myname);
+ warnx("Authentication failed");
+ return AUTH_FAILED;
+ }
+ explicit_bzero(rbuf, sizeof(rbuf));
+ return AUTH_OK;
+}
+
+static void
+authuser(char *myname, char *login_style, int persist)
+{
+ int i, fd = -1;
+
+ if (persist)
+ fd = open("/dev/tty", O_RDWR);
+ if (fd != -1) {
+ if (ioctl(fd, TIOCCHKVERAUTH) == 0)
+ goto good;
+ }
+ for (i = 0; i < AUTH_RETRIES; i++) {
+ if (authuser_checkpass(myname, login_style) == AUTH_OK)
+ goto good;
+ }
+ exit(1);
+good:
+ if (fd != -1) {
+ int secs = 5 * 60;
+ ioctl(fd, TIOCSETVERAUTH, &secs);
+ close(fd);
+ }
+}
+
+int
+unveilcommands(const char *ipath, const char *cmd)
+{
+ char *path = NULL, *p;
+ int unveils = 0;
+
+ if (strchr(cmd, '/') != NULL) {
+ if (unveil(cmd, "x") != -1)
+ unveils++;
+ goto done;
+ }
+
+ if (!ipath) {
+ errno = ENOENT;
+ goto done;
+ }
+ path = strdup(ipath);
+ if (!path) {
+ errno = ENOENT;
+ goto done;
+ }
+ for (p = path; p && *p; ) {
+ char buf[PATH_MAX];
+ char *cp = strsep(&p, ":");
+
+ if (cp) {
+ int r = snprintf(buf, sizeof buf, "%s/%s", cp, cmd);
+ if (r >= 0 && r < sizeof buf) {
+ if (unveil(buf, "x") != -1)
+ unveils++;
+ }
+ }
+ }
+done:
+ free(path);
+ return (unveils);
+}
+
+int
+main(int argc, char **argv)
+{
+ const char *safepath = "/bin:/sbin:/usr/bin:/usr/sbin:"
+ "/usr/local/bin:/usr/local/sbin";
+ const char *confpath = NULL;
+ char *shargv[] = { NULL, NULL };
+ char *sh;
+ const char *p;
+ const char *cmd;
+ char cmdline[LINE_MAX];
+ char mypwbuf[_PW_BUF_LEN], targpwbuf[_PW_BUF_LEN];
+ struct passwd mypwstore, targpwstore;
+ struct passwd *mypw, *targpw;
+ const struct rule *rule;
+ uid_t uid;
+ uid_t target = 0;
+ gid_t groups[NGROUPS_MAX + 1];
+ int ngroups;
+ int i, ch, rv;
+ int sflag = 0;
+ int nflag = 0;
+ char cwdpath[PATH_MAX];
+ const char *cwd;
+ char *login_style = NULL;
+ char **envp;
+
+ setprogname("doas");
+
+ closefrom(STDERR_FILENO + 1);
+
+ uid = getuid();
+
+ while ((ch = getopt(argc, argv, "a:C:Lnsu:")) != -1) {
+ switch (ch) {
+ case 'a':
+ login_style = optarg;
+ break;
+ case 'C':
+ confpath = optarg;
+ break;
+ case 'L':
+ i = open("/dev/tty", O_RDWR);
+ if (i != -1)
+ ioctl(i, TIOCCLRVERAUTH);
+ exit(i == -1);
+ case 'u':
+ if (parseuid(optarg, &target) != 0)
+ errx(1, "unknown user");
+ break;
+ case 'n':
+ nflag = 1;
+ break;
+ case 's':
+ sflag = 1;
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+ argv += optind;
+ argc -= optind;
+
+ if (confpath) {
+ if (sflag)
+ usage();
+ } else if ((!sflag && !argc) || (sflag && argc))
+ usage();
+
+ rv = getpwuid_r(uid, &mypwstore, mypwbuf, sizeof(mypwbuf), &mypw);
+ if (rv != 0)
+ err(1, "getpwuid_r failed");
+ if (mypw == NULL)
+ errx(1, "no passwd entry for self");
+ ngroups = getgroups(NGROUPS_MAX, groups);
+ if (ngroups == -1)
+ err(1, "can't get groups");
+ groups[ngroups++] = getgid();
+
+ if (sflag) {
+ sh = getenv("SHELL");
+ if (sh == NULL || *sh == '\0') {
+ shargv[0] = mypw->pw_shell;
+ } else
+ shargv[0] = sh;
+ argv = shargv;
+ argc = 1;
+ }
+
+ if (confpath) {
+ if (pledge("stdio rpath getpw id", NULL) == -1)
+ err(1, "pledge");
+ checkconfig(confpath, argc, argv, uid, groups, ngroups,
+ target);
+ exit(1); /* fail safe */
+ }
+
+ if (geteuid())
+ errx(1, "not installed setuid");
+
+ parseconfig("/etc/doas.conf", 1);
+
+ /* cmdline is used only for logging, no need to abort on truncate */
+ (void)strlcpy(cmdline, argv[0], sizeof(cmdline));
+ for (i = 1; i < argc; i++) {
+ if (strlcat(cmdline, " ", sizeof(cmdline)) >= sizeof(cmdline))
+ break;
+ if (strlcat(cmdline, argv[i], sizeof(cmdline)) >= sizeof(cmdline))
+ break;
+ }
+
+ cmd = argv[0];
+ rv = permit(uid, groups, ngroups, &rule, target, cmd,
+ (const char **)argv + 1);
+ if (rv != 0) {
+ syslog(LOG_AUTHPRIV | LOG_NOTICE,
+ "command not permitted for %s: %s", mypw->pw_name, cmdline);
+ errc(1, EPERM, NULL);
+ }
+
+ if (!(rule->options & NOPASS)) {
+ if (nflag)
+ errx(1, "Authentication required");
+
+ authuser(mypw->pw_name, login_style, rule->options & PERSIST);
+ }
+
+ if ((p = getenv("PATH")) != NULL)
+ formerpath = strdup(p);
+ if (formerpath == NULL)
+ formerpath = "";
+
+ if (unveil(_PATH_LOGIN_CONF, "r") == -1)
+ err(1, "unveil %s", _PATH_LOGIN_CONF);
+ if (unveil(_PATH_LOGIN_CONF ".db", "r") == -1)
+ err(1, "unveil %s.db", _PATH_LOGIN_CONF);
+ if (unveil(_PATH_LOGIN_CONF_D, "r") == -1)
+ err(1, "unveil %s", _PATH_LOGIN_CONF_D);
+ if (rule->cmd) {
+ if (setenv("PATH", safepath, 1) == -1)
+ err(1, "failed to set PATH '%s'", safepath);
+ }
+ if (unveilcommands(getenv("PATH"), cmd) == 0)
+ goto fail;
+
+ if (pledge("stdio rpath getpw exec id", NULL) == -1)
+ err(1, "pledge");
+
+ rv = getpwuid_r(target, &targpwstore, targpwbuf, sizeof(targpwbuf), &targpw);
+ if (rv != 0)
+ err(1, "getpwuid_r failed");
+ if (targpw == NULL)
+ errx(1, "no passwd entry for target");
+
+ if (setusercontext(NULL, targpw, target, LOGIN_SETGROUP |
+ LOGIN_SETPATH |
+ LOGIN_SETPRIORITY | LOGIN_SETRESOURCES | LOGIN_SETUMASK |
+ LOGIN_SETUSER | LOGIN_SETENV | LOGIN_SETRTABLE) != 0)
+ errx(1, "failed to set user context for target");
+
+ if (pledge("stdio rpath exec", NULL) == -1)
+ err(1, "pledge");
+
+ if (getcwd(cwdpath, sizeof(cwdpath)) == NULL)
+ cwd = "(failed)";
+ else
+ cwd = cwdpath;
+
+ if (pledge("stdio exec", NULL) == -1)
+ err(1, "pledge");
+
+ if (!(rule->options & NOLOG)) {
+ syslog(LOG_AUTHPRIV | LOG_INFO,
+ "%s ran command %s as %s from %s",
+ mypw->pw_name, cmdline, targpw->pw_name, cwd);
+ }
+
+ envp = prepenv(rule, mypw, targpw);
+
+ /* setusercontext set path for the next process, so reset it for us */
+ if (rule->cmd) {
+ if (setenv("PATH", safepath, 1) == -1)
+ err(1, "failed to set PATH '%s'", safepath);
+ } else {
+ if (setenv("PATH", formerpath, 1) == -1)
+ err(1, "failed to set PATH '%s'", formerpath);
+ }
+ execvpe(cmd, argv, envp);
+fail:
+ if (errno == ENOENT)
+ errx(1, "%s: command not found", cmd);
+ err(1, "%s", cmd);
+}
diff --git a/openbsd-pledge-unveil/openbsd-7.6.jpg b/openbsd-pledge-unveil/openbsd-7.6.jpg
new file mode 100644
index 0000000..7d9cd50
Binary files /dev/null and b/openbsd-pledge-unveil/openbsd-7.6.jpg differ
diff --git a/openbsd-pledge-unveil/openbsd-pledge-unveil.md b/openbsd-pledge-unveil/openbsd-pledge-unveil.md
new file mode 100755
index 0000000..7e4ab76
--- /dev/null
+++ b/openbsd-pledge-unveil/openbsd-pledge-unveil.md
@@ -0,0 +1,389 @@
+#!/bin/env slides
+
+# OpenBSD, pledge(), and unveil()
+
+_By Bruce Hill_
+
+```
+ _.-|-/\-._
+ \-' '-.
+ / /\ /\ \/ _____ ____ _____ _____
+ \/ < . > ./. \/ / ___ \ | _ \ / ____| __ \
+ _ / < > /___\ |. / / / /___ ___ ____ | |_) | (___ | | | |
+.< \ / < /\ > ( #) |#) / / / / __ \/ _ \/ __ \| _ < \___ \| | | |
+ | | < /\ -. __\ / /__/ / /_/ / __/ / / /| |_) |____) | |__| |
+ \ < < V > )./_._(\ \_____/ .___/\___/_/ /_/ |____/|_____/|_____/
+ .)/\ < < .- / \_'_) )-.. /_/
+ \ < ./ / > > /._./
+ /\ < '-' > > /
+ '-._ < v > _.-'
+ / '-.______.-' \
+ \/
+```
+
+(Puffy the OpenBSD mascot)
+
+---------------------------------
+
+# OpenBSD
+
+- BSD = Berkeley Software Distribution
+ - Also known as "Berkeley Unix"
+ - MacOS is based on BSD
+
+```demo
+sxiv -sf -f os-family-tree.png
+```
+
+- Kinda like Linux, but cooler!
+ - Better security
+ - Simpler design
+ - ...but maybe worse for personal computing
+ - But great for web servers!
+- My website runs on OpenBSD!
+
+----------------------------------
+
+# Linux Analogy
+
+The BSD Family:
+
+- **FreeBSD:** the _Ubuntu_ of the BSD family
+ - Relatively user-friendly
+ - Good for desktops
+- **NetBSD:** the _Linux Mint_ of the BSD family
+ - Very portable
+ - Good for low-resource machines
+- **OpenBSD:** the _Arch/Qubes_ of the BSD family
+ - Great documentation (manpages)
+ - **High emphasis on security**
+
+--------------------------------------
+
+# OpenBSD
+
+- Probably more secure than any OS you've ever used
+ - Maybe Qubes is a contender? Debatable.
+- Really excellent code quality
+ - Great learning resource
+- Ports collection for package management
+ - Very cool, but out of scope for today
+- Numerous security improvements exported to other platforms:
+ - OpenSSH
+ - `strlcpy()`
+ - `arc4random()`
+- Some security improvements that **should** be exported:
+ - `unveil()`
+ - `pledge()`
+
+-------------------------------------
+
+# Tangent: Release Artwork
+
+
+
+-------------------------------------
+
+# Tangent: Release Artwork
+
+[Every OS release has artwork and music made by the community](https://www.openbsd.org/artwork.html)
+
+Every six months since 1996!
+
+-------------------------------------
+
+# Defense in Depth
+
+OpenBSD operates on the assumption that users
+**will** write and run software with bugs.
+
+**What happens next will amaze you!**
+
+When a program starts, it has some idea of what the
+expected behavior will be.
+
+- Which files or directories it needs to access
+- Which system calls will be needed
+- What _kind of thing_ the program is doing
+
+The idea is to **pre-commit** to only doing those things.
+
+If a program has a bug that allows for unintended behavior,
+**OpenBSD will limit the fallout of that bug.**
+
+----------------------------------
+
+# Unveil
+
+```c
+int unveil(const char *path, const char *permissions)
+```
+
+When a program starts, it can restrict itself
+to certain parts of the filesystem with `unveil()`
+
+- Limit which files and directories the program can see
+- Change whether the program has read/write/execute permissions on files
+
+This is **enforced by the OS** and it will cause
+system calls like `open()` to return error values as
+if those files didn't exist or didn't have those
+permissions.
+
+Unveil is **additive** so once you call it, it
+closes off access to all files on the filesystem
+except the ones you _add_ access to.
+
+```demo
+less unveil.txt
+```
+
+----------------------------------
+
+# Chroot Jail Comparison
+
+`unveil()` is similar to `chroot`, but much, much
+easier to use.
+
+**Chroot:**
+
+- Run a program in a fake (restricted) filesystem
+- Only include copies of stuff you want
+- Run your program so it thinks that is the whole filesystem
+- Annoying to set up
+- Requires copying files
+
+**Unveil:**
+
+- Selectively mask off parts of the existing filesystem
+- Easy to add a few function calls or wrap a program
+- Don't need to copy any files
+- Can easily do read-only or write-only access
+
+----------------------------------
+
+# Using unveil()
+
+`unveil()` is a drop-in security measure that can make
+a program more secure _without invasive changes._
+
+You _just_ have to add a call to `unveil()` to the
+top of your program and any program that correctly
+handles non-existent files works as you would hope.
+
+```python
+def buggy_write_to_tempfile(filename: str, contents: str):
+ with open("/tmp/" + filename, "w") as f:
+ f.write(contents)
+
+# Uh oh!
+buggy_write_to_tempfile("../etc/passwd", "Oh no")
+```
+
+Let's make it secure:
+
+```python
+import openbsd
+openbsd.unveil("/tmp", "rw")
+
+# Now this is safe(r)!
+buggy_write_to_tempfile("../etc/passwd", "Oh no")
+```
+
+Now we can't read or write any file outside of `/tmp`!
+
+----------------------------------
+
+# Pledge
+
+```c
+int pledge(const char *promises, const char *execpromises)
+```
+
+`pledge()` lets you restrict which **system calls**
+the current program is allowed to make (and which
+ones any child processes can make).
+
+Some interesting permissions:
+
+- `stdio`: do standard I/O operations like reading `stdin` and printing to `stdout`
+- `rpath`: perform **read-only** operations on the filesystem (e.g. `cat`)
+- `wpath`: perform **write-only** operations on the filesystem (e.g. a logger)
+- `inet`: do networking stuff like access the internet
+- `exec`: execute other programs
+- `unveil`: call `unveil()` to allow access to more files **(!!!)**
+
+```demo
+less pledge.txt
+```
+
+----------------------------------
+
+# Pledge Case Study: Echo
+
+The `echo` program in the OpenBSD codebase
+(slightly modified)
+
+```c
+int main(int argc, char *argv[]) {
+ if (pledge("stdio", NULL) == -1)
+ err(1, "pledge");
+
+ while (*argv) {
+ (void)fputs(*argv, stdout);
+ if (*++argv)
+ putchar(' ');
+ }
+ putchar('\n');
+
+ return 0;
+}
+```
+
+Even if there were a bug in this program, it is
+_near impossible_ for the program to do anything other
+than read `stdin` and print to `stdout`!
+
+----------------------------------
+
+# Pledge Narrowing: cat
+
+Another useful technique is to start with maximum
+permissions and gradually drop permissions as you go.
+
+Here's a [simplified](https://github.com/openbsd/src/blob/master/bin/cat/cat.c) version of `cat`:
+
+```c
+int main(int argc, char *argv[]) {
+ pledge("stdio rpath", NULL);
+
+ FILE *f = argc == 1 ? stdout : fopen(argv[1], "r");
+
+ // Don't need FS read permissions anymore
+ pledge("stdio", NULL);
+
+ char buf[100];
+ size_t just_read;
+ while ((just_read=fread(buf, 1, sizeof(buf), f)) > 0)
+ fwrite(buf, 1, just_read, stdout);
+
+ fclose(f);
+ return 0;
+}
+```
+
+**💀 BAD PRACTICE: not checking return values 💀**
+
+----------------------------------
+
+# Combined pledge/unveil Example
+
+From `fsck.c`, which checks the filesystem:
+
+```c
+if (unveil("/dev", "rw") == -1)
+ err(1, "unveil /dev");
+if (unveil("/etc/fstab", "r") == -1)
+ err(1, "unveil %s", _PATH_FSTAB);
+if (unveil("/sbin", "x") == -1)
+ err(1, "unveil /sbin");
+if (pledge("stdio rpath wpath disklabel proc exec", NULL) == -1)
+ err(1, "pledge");
+```
+
+It can:
+
+1. Read and write to `/dev`
+2. Read `/etc/fstab`
+3. Run programs in `/sbin`
+4. Do I/O, filesystem stuff, and run programs from `/sbin`
+
+It cannot:
+
+1. Access password files
+2. Read from user's home directory
+3. Write files anywhere besides `/dev`
+4. Connect to the internet
+5. Kill other processes
+6. **Change my `pledge()`/`unveil()` permissions further (!!!)**
+
+----------------------------------
+# Case Study: Firefox
+
+>Firefox on OpenBSD is secured with pledge(2) and unveil(2)
+>to limit the system calls and filesystem access that each
+>of Firefox's process types (main, content, remote data decoder,
+>audio decoder, socket and GPU) is permitted.
+>**By default, only ~/Downloads and /tmp can be written to**
+>when downloading files, or when viewing local files
+>as file:// URLs.
+
+Even if there are bugs in a massive program like Firefox,
+the scope of the damage an attacker could do is limited!
+
+----------------------------------
+
+# Conclusion
+
+I hope you think these security tools are as cool as I do!
+
+OpenBSD is a really great OS to run on a web server where
+you care a lot about security!
+
+Most of the built-in software that ships with the OS makes
+good use of `pledge()` and `unveil()` to give you better
+security!
+
+Try it yourself sometime! It's mostly familiar to Mac/Linux
+users, but with a few galaxy brain ideas.
+
+----------------------------------
+
+# The End
+
+_Thanks for your time!_
+
+----------------------------------
+
+# Footnote 1: Code Quality
+
+Compare OpenBSD's implementation of `true`:
+
+
+
+With the GNU Coure Utilities implementation used in Linux:
+
+
+
+----------------------------------
+
+# Footnote 2: Code Quality
+
+OpenBSD comes with `doas`, which is under 500 lines of code:
+
+```
+*******************************************************************************
+Language files blank comment code
+*******************************************************************************
+C 1 55 19 424
+*******************************************************************************
+```
+
+The `sudo` that comes with Linux is nearly a quarter million lines of code!
+
+```
+*******************************************************************************
+Language files blank comment code
+*******************************************************************************
+C 468 18,038 28,119 132,203
+PO File 74 30,350 48,907 78,866
+Bourne Shell 94 8,868 6,387 51,341
+m4 24 1336 607 14,761
+...
+*******************************************************************************
+SUM: 717 59,673 85,426 284,387
+*******************************************************************************
+```
+
+[More lines of code = more risk of vulnerabilities](https://www.alibabacloud.com/help/en/ecs/vulnerability-announcement-or-linux-sudo-permission-vulnerability)
+
diff --git a/openbsd-pledge-unveil/openbsd-true.c b/openbsd-pledge-unveil/openbsd-true.c
new file mode 100644
index 0000000..90ecce6
--- /dev/null
+++ b/openbsd-pledge-unveil/openbsd-true.c
@@ -0,0 +1,9 @@
+/* $OpenBSD: true.c,v 1.1 2015/11/11 19:05:28 deraadt Exp $ */
+
+/* Public domain - Theo de Raadt */
+
+ int
+main(int argc, char *argv[])
+{
+ return (0);
+}
diff --git a/openbsd-pledge-unveil/os-family-tree.png b/openbsd-pledge-unveil/os-family-tree.png
new file mode 100644
index 0000000..db1b5f3
Binary files /dev/null and b/openbsd-pledge-unveil/os-family-tree.png differ
diff --git a/openbsd-pledge-unveil/pledge.txt b/openbsd-pledge-unveil/pledge.txt
new file mode 100644
index 0000000..52dd7da
--- /dev/null
+++ b/openbsd-pledge-unveil/pledge.txt
@@ -0,0 +1,300 @@
+PLEDGE(2) System Calls Manual PLEDGE(2)
+
+NNAAMMEE
+ pplleeddggee - restrict system operations
+
+SSYYNNOOPPSSIISS
+ ##iinncclluuddee <>
+
+ _i_n_t
+ pplleeddggee(_c_o_n_s_t _c_h_a_r _*_p_r_o_m_i_s_e_s, _c_o_n_s_t _c_h_a_r _*_e_x_e_c_p_r_o_m_i_s_e_s);
+
+DDEESSCCRRIIPPTTIIOONN
+ The pplleeddggee() system call forces the current process into a restricted-
+ service operating mode. A few subsets are available, roughly described
+ as computation, memory management, read-write operations on file
+ descriptors, opening of files, networking (and notably separate, DNS
+ resolution). In general, these modes were selected by studying the
+ operation of many programs using libc and other such interfaces, and
+ setting _p_r_o_m_i_s_e_s or _e_x_e_c_p_r_o_m_i_s_e_s.
+
+ Use of pplleeddggee() in an application will require at least some study and
+ understanding of the interfaces called. Subsequent calls to pplleeddggee() can
+ reduce the abilities further, but abilities can never be regained.
+
+ A process which attempts a restricted operation is killed with an
+ uncatchable SIGABRT, delivering a core file if possible. A process
+ currently running with pledge has state `p' in ps(1) output; a process
+ that was terminated due to a pledge violation is accounted by lastcomm(1)
+ with the `P' flag.
+
+ A _p_r_o_m_i_s_e_s value of "" restricts the process to the _exit(2) system call.
+ This can be used for pure computation operating on memory shared with
+ another process.
+
+ Passing NULL to _p_r_o_m_i_s_e_s or _e_x_e_c_p_r_o_m_i_s_e_s specifies to not change the
+ current value.
+
+ Some system calls, when allowed, have restrictions applied to them:
+
+ access(2):
+ May check for existence of _/_e_t_c_/_l_o_c_a_l_t_i_m_e.
+
+ adjtime(2):
+ Read-only, for ntpd(8).
+
+ chmod(2), fchmod(2), fchmodat(2), chown(2), lchown(2), fchown(2),
+ fchownat(2), mkfifo(2), and mknod(2):
+ Setuid/setgid/sticky bits are ignored. The user or group cannot be
+ changed on a file.
+
+ ioctl(2):
+ Only the FIONREAD, FIONBIO, FIOCLEX, and FIONCLEX operations are
+ allowed by default. Various ioctl requests are allowed against
+ specific file descriptors based upon the requests aauuddiioo, bbppff,
+ ddiisskkllaabbeell, ddrrmm, iinneett, ppff, rroouuttee, wwrroouuttee, ttaappee, ttttyy, vviiddeeoo, and vvmmmm.
+
+ mmap(2) and mprotect(2):
+ PROT_EXEC isn't allowed.
+
+ open(2):
+ May open _/_e_t_c_/_l_o_c_a_l_t_i_m_e and any files below _/_u_s_r_/_s_h_a_r_e_/_z_o_n_e_i_n_f_o.
+
+ profil(2):
+ Can only disable profiling.
+
+ pplleeddggee():
+ Can only reduce permissions for _p_r_o_m_i_s_e_s and _e_x_e_c_p_r_o_m_i_s_e_s.
+
+ sysctl(2):
+ A small set of read-only operations are allowed, sufficient to
+ support: getdomainname(3), gethostname(3), getifaddrs(3), uname(3),
+ and system sensor readings.
+
+ The _p_r_o_m_i_s_e_s argument is specified as a string, with space separated
+ keywords:
+
+ ssttddiioo The following system calls are permitted. sendto(2) is
+ only permitted if its destination socket address is
+ NULL. As a result, all the expected functionalities of
+ libc stdio work.
+
+ clock_getres(2), clock_gettime(2), close(2),
+ closefrom(2), dup(2), dup2(2), dup3(2), fchdir(2),
+ fcntl(2), fstat(2), fsync(2), ftruncate(2),
+ getdtablecount(2), getegid(2), getentropy(2),
+ geteuid(2), getgid(2), getgroups(2), getitimer(2),
+ getlogin(2), getpgid(2), getpgrp(2), getpid(2),
+ getppid(2), getresgid(2), getresuid(2), getrlimit(2),
+ getrtable(2), getsid(2), getthrid(2), gettimeofday(2),
+ getuid(2), issetugid(2), kevent(2), kqueue(2),
+ kqueue1(2), lseek(2), madvise(2), minherit(2), mmap(2),
+ mprotect(2), mquery(2), munmap(2), nanosleep(2),
+ pipe(2), pipe2(2), poll(2), pread(2), preadv(2),
+ profil(2), pwrite(2), pwritev(2), read(2), readv(2),
+ recvfrom(2), recvmsg(2), select(2), sendmsg(2),
+ sendsyslog(2), sendto(2), setitimer(2), shutdown(2),
+ sigaction(2), sigprocmask(2), sigreturn(2),
+ socketpair(2), umask(2), wait4(2), waitid(2), write(2),
+ writev(2)
+
+ rrppaatthh A number of system calls are allowed if they only cause
+ read-only effects on the filesystem, or expose filenames
+ to programs:
+
+ chdir(2), getcwd(3), getdents(2), openat(2), fstatat(2),
+ faccessat(2), readlinkat(2), lstat(2), chmod(2),
+ fchmod(2), fchmodat(2), chflags(2), chflagsat(2),
+ chown(2), fchown(2), fchownat(2), fstat(2), getfsstat(2)
+
+ wwppaatthh A number of system calls are allowed and may cause
+ write-effects on the filesystem:
+
+ getcwd(3), openat(2), fstatat(2), faccessat(2),
+ readlinkat(2), lstat(2), chmod(2), fchmod(2),
+ fchmodat(2), chflags(2), chflagsat(2), chown(2),
+ fchown(2), fchownat(2), fstat(2)
+
+ ccppaatthh A number of system calls and sub-modes are allowed,
+ which may create new files or directories in the
+ filesystem:
+
+ rename(2), renameat(2), link(2), linkat(2), symlink(2),
+ symlinkat(2), unlink(2), unlinkat(2), mkdir(2),
+ mkdirat(2), rmdir(2)
+
+ ddppaatthh A number of system calls are allowed to create special
+ files:
+
+ mkfifo(2), mknod(2)
+
+ ttmmppppaatthh A number of system calls are allowed to do operations in
+ the _/_t_m_p directory, including create, read, or write:
+
+ lstat(2), chmod(2), chflags(2), chown(2), unlink(2),
+ fstat(2)
+
+ iinneett The following system calls are allowed to operate in the
+ AF_INET and AF_INET6 domains (though setsockopt(2) has
+ been substantially reduced in functionality):
+
+ socket(2), listen(2), bind(2), connect(2), accept4(2),
+ accept(2), getpeername(2), getsockname(2),
+ setsockopt(2), getsockopt(2)
+
+ mmccaasstt In combination with iinneett give back functionality to
+ setsockopt(2) for operating on multicast sockets.
+
+ ffaattttrr The following system calls are allowed to make explicit
+ changes to fields in _s_t_r_u_c_t _s_t_a_t relating to a file:
+
+ utimes(2), futimes(2), utimensat(2), futimens(2),
+ chmod(2), fchmod(2), fchmodat(2), chflags(2),
+ chflagsat(2), chown(2), fchownat(2), lchown(2),
+ fchown(2), utimes(2)
+
+ cchhoowwnn The chown(2) family is allowed to change the user or
+ group on a file.
+
+ fflloocckk File locking via fcntl(2), flock(2), lockf(3), and
+ open(2) is allowed. No distinction is made between
+ shared and exclusive locks. This promise is required
+ for unlock as well as lock.
+
+ uunniixx The following system calls are allowed to operate in the
+ AF_UNIX domain:
+
+ socket(2), listen(2), bind(2), connect(2), accept4(2),
+ accept(2), getpeername(2), getsockname(2),
+ setsockopt(2), getsockopt(2)
+
+ ddnnss Subsequent to a successful open(2) of _/_e_t_c_/_r_e_s_o_l_v_._c_o_n_f,
+ a few system calls become able to allow DNS network
+ transactions:
+
+ sendto(2), recvfrom(2), socket(2), connect(2)
+
+ ggeettppww This allows read-only opening of files in _/_e_t_c for the
+ getpwnam(3), getgrnam(3), getgrouplist(3), and
+ initgroups(3) family of functions, including lookups via
+ the yp(8) protocol for YP and LDAP databases.
+
+ sseennddffdd Allows sending of file descriptors using sendmsg(2).
+ File descriptors referring to directories may not be
+ passed.
+
+ rreeccvvffdd Allows receiving of file descriptors using recvmsg(2).
+ File descriptors referring to directories may not be
+ passed.
+
+ ttaappee Allow MTIOCGET and MTIOCTOP operations against tape
+ drives.
+
+ ttttyy In addition to allowing read-write operations on
+ _/_d_e_v_/_t_t_y, this opens up a variety of ioctl(2) requests
+ used by tty devices. If ttttyy is accompanied with rrppaatthh,
+ revoke(2) is permitted. Otherwise only the following
+ ioctl(2) requests are permitted:
+
+ TIOCSPGRP, TIOCGETA, TIOCGPGRP, TIOCGWINSZ, TIOCSWINSZ,
+ TIOCSBRK, TIOCCDTR, TIOCSETA, TIOCSETAW, TIOCSETAF,
+ TIOCUCNTL
+
+ pprroocc Allows the following process relationship operations:
+
+ fork(2), vfork(2), kill(2), getpriority(2),
+ setpriority(2), setrlimit(2), setpgid(2), setsid(2)
+
+ eexxeecc Allows a process to call execve(2). Coupled with the
+ pprroocc promise, this allows a process to fork and execute
+ another program. If _e_x_e_c_p_r_o_m_i_s_e_s has been previously
+ set the new program begins with those promises, unless
+ setuid/setgid bits are set in which case execution is
+ blocked with EACCES. Otherwise the new program starts
+ running without pledge active, and hopefully makes a new
+ pledge soon.
+
+ pprroott__eexxeecc Allows the use of PROT_EXEC with mmap(2) and
+ mprotect(2).
+
+ sseettttiimmee Allows the setting of system time, via the
+ settimeofday(2), adjtime(2), and adjfreq(2) system
+ calls.
+
+ ppss Allows enough sysctl(2) interfaces to allow inspection
+ of processes operating on the system using programs like
+ ps(1).
+
+ vvmmiinnffoo Allows enough sysctl(2) interfaces to allow inspection
+ of the system's virtual memory by programs like top(1)
+ and vmstat(8).
+
+ iidd Allows the following system calls which can change the
+ rights of a process:
+
+ setuid(2), seteuid(2), setreuid(2), setresuid(2),
+ setgid(2), setegid(2), setregid(2), setresgid(2),
+ setgroups(2), setlogin(2), setrlimit(2), getpriority(2),
+ setpriority(2), setrtable(2)
+
+ ppff Allows a subset of ioctl(2) operations on the pf(4)
+ device:
+
+ DIOCADDRULE, DIOCGETSTATUS, DIOCNATLOOK, DIOCRADDTABLES,
+ DIOCRCLRADDRS, DIOCRCLRTABLES, DIOCRCLRTSTATS,
+ DIOCRGETTSTATS, DIOCRSETADDRS, DIOCXBEGIN, DIOCXCOMMIT
+
+ rroouuttee Allow inspection of the routing table.
+
+ wwrroouuttee Allow changes to the routing table.
+
+ aauuddiioo Allows a subset of ioctl(2) operations on audio(4)
+ devices (see sio_open(3) for more information):
+
+ AUDIO_GETPOS, AUDIO_GETPAR, AUDIO_SETPAR, AUDIO_START,
+ AUDIO_STOP, AUDIO_MIXER_DEVINFO, AUDIO_MIXER_READ,
+ AUDIO_MIXER_WRITE
+
+ vviiddeeoo Allows a subset of ioctl(2) operations on video(4)
+ devices:
+
+ VIDIOC_DQBUF, VIDIOC_ENUM_FMT,
+ VIDIOC_ENUM_FRAMEINTERVALS, VIDIOC_ENUM_FRAMESIZES,
+ VIDIOC_G_CTRL, VIDIOC_G_PARM, VIDIOC_QBUF,
+ VIDIOC_QUERYBUF, VIDIOC_QUERYCAP, VIDIOC_QUERYCTRL,
+ VIDIOC_S_CTRL, VIDIOC_S_FMT, VIDIOC_S_PARM,
+ VIDIOC_STREAMOFF, VIDIOC_STREAMON, VIDIOC_TRY_FMT,
+ VIDIOC_REQBUFS
+
+ bbppff Allow BIOCGSTATS operation for statistics collection
+ from a bpf(4) device.
+
+ uunnvveeiill Allow unveil(2) to be called.
+
+ eerrrroorr Rather than killing the process upon violation, indicate
+ error with ENOSYS.
+
+ Also when pplleeddggee() is called with higher _p_r_o_m_i_s_e_s or
+ _e_x_e_c_p_r_o_m_i_s_e_s, those changes will be ignored and return
+ success. This is useful when a parent enforces
+ _e_x_e_c_p_r_o_m_i_s_e_s but an execve'd child has a different idea.
+
+RREETTUURRNN VVAALLUUEESS
+ Upon successful completion, the value 0 is returned; otherwise the
+ value -1 is returned and the global variable _e_r_r_n_o is set to indicate the
+ error.
+
+EERRRROORRSS
+ pplleeddggee() will fail if:
+
+ [EFAULT] _p_r_o_m_i_s_e_s or _e_x_e_c_p_r_o_m_i_s_e_s points outside the process's
+ allocated address space.
+
+ [EINVAL] _p_r_o_m_i_s_e_s is malformed or contains invalid keywords.
+
+ [EPERM] This process is attempting to increase permissions.
+
+HHIISSTTOORRYY
+ The pplleeddggee() system call first appeared in OpenBSD 5.9.
+
+OpenBSD 7.6 September 17, 2024 OpenBSD 7.6
diff --git a/openbsd-pledge-unveil/unveil.txt b/openbsd-pledge-unveil/unveil.txt
new file mode 100644
index 0000000..f940ab3
--- /dev/null
+++ b/openbsd-pledge-unveil/unveil.txt
@@ -0,0 +1,81 @@
+UNVEIL(2) System Calls Manual UNVEIL(2)
+
+NNAAMMEE
+ uunnvveeiill - unveil parts of a restricted filesystem view
+
+SSYYNNOOPPSSIISS
+ ##iinncclluuddee <>
+
+ _i_n_t
+ uunnvveeiill(_c_o_n_s_t _c_h_a_r _*_p_a_t_h, _c_o_n_s_t _c_h_a_r _*_p_e_r_m_i_s_s_i_o_n_s);
+
+DDEESSCCRRIIPPTTIIOONN
+ The first call to uunnvveeiill() that specifies a _p_a_t_h removes visibility of
+ the entire filesystem from all other filesystem-related system calls
+ (such as open(2), chmod(2) and rename(2)), except for the specified _p_a_t_h
+ and _p_e_r_m_i_s_s_i_o_n_s.
+
+ The uunnvveeiill() system call remains capable of traversing to any _p_a_t_h in the
+ filesystem, so additional calls can set permissions at other points in
+ the filesystem hierarchy.
+
+ After establishing a collection of _p_a_t_h and _p_e_r_m_i_s_s_i_o_n_s rules, future
+ calls to uunnvveeiill() can be disabled by passing two NULL arguments.
+ Alternatively, pledge(2) may be used to remove the "unveil" promise.
+
+ The _p_e_r_m_i_s_s_i_o_n_s argument points to a string consisting of zero or more of
+ the following characters:
+
+ rr Make _p_a_t_h available for read operations, corresponding to the
+ pledge(2) promise "rpath".
+ ww Make _p_a_t_h available for write operations, corresponding to
+ the pledge(2) promise "wpath".
+ xx Make _p_a_t_h available for execute operations, corresponding to
+ the pledge(2) promise "exec".
+ cc Allow _p_a_t_h to be created and removed, corresponding to the
+ pledge(2) promise "cpath".
+
+ A _p_a_t_h that is a directory will enable all filesystem access underneath
+ _p_a_t_h using _p_e_r_m_i_s_s_i_o_n_s if and only if no more specific matching uunnvveeiill()
+ exists at a lower level. Directories are remembered at the time of a
+ call to uunnvveeiill(). This means that a directory that is removed and
+ recreated after a call to uunnvveeiill() will appear to not exist.
+
+ Non-directory paths are remembered by name within their containing
+ directory, and so may be created, removed, or re-created after a call to
+ uunnvveeiill() and still appear to exist.
+
+ Attempts to access paths not allowed by uunnvveeiill() will result in an error
+ of EACCES when the _p_e_r_m_i_s_s_i_o_n_s argument does not match the attempted
+ operation. ENOENT is returned for paths for which no uunnvveeiill()
+ permissions qualify. After a process has terminated, lastcomm(1) will
+ mark it with the `U' flag if file access was prevented by uunnvveeiill().
+
+ uunnvveeiill() use can be tricky because programs misbehave badly when their
+ files unexpectedly disappear. In many cases it is easier to unveil the
+ directories in which an application makes use of files.
+
+RREETTUURRNN VVAALLUUEESS
+ Upon successful completion, the value 0 is returned; otherwise the
+ value -1 is returned and the global variable _e_r_r_n_o is set to indicate the
+ error.
+
+EERRRROORRSS
+ [E2BIG] The addition of _p_a_t_h would exceed the per-process
+ limit for unveiled paths.
+
+ [EFAULT] _p_a_t_h or _p_e_r_m_i_s_s_i_o_n_s points outside the process's
+ allocated address space.
+
+ [ENOENT] A directory in _p_a_t_h did not exist.
+
+ [EINVAL] An invalid value of _p_e_r_m_i_s_s_i_o_n_s was used.
+
+ [EPERM] An attempt to increase permissions was made, or the
+ _p_a_t_h was not accessible, or uunnvveeiill() was called after
+ locking.
+
+HHIISSTTOORRYY
+ The uunnvveeiill() system call first appeared in OpenBSD 6.4.
+
+OpenBSD 7.6 September 6, 2021 OpenBSD 7.6