summaryrefslogtreecommitdiff
path: root/regress/sys
diff options
context:
space:
mode:
Diffstat (limited to 'regress/sys')
-rw-r--r--regress/sys/kern/setuid/Makefile115
-rw-r--r--regress/sys/kern/setuid/setegid.c64
-rw-r--r--regress/sys/kern/setuid/seteuid.c66
-rw-r--r--regress/sys/kern/setuid/setgid.c52
-rw-r--r--regress/sys/kern/setuid/setgid_child.c75
-rw-r--r--regress/sys/kern/setuid/setgid_exec_inherit.c51
-rw-r--r--regress/sys/kern/setuid/setgid_none.c44
-rw-r--r--regress/sys/kern/setuid/setresgid.c102
-rw-r--r--regress/sys/kern/setuid/setresgid_effective_exec.c62
-rw-r--r--regress/sys/kern/setuid/setresgid_real_exec.c62
-rw-r--r--regress/sys/kern/setuid/setresgid_saved_exec.c62
-rw-r--r--regress/sys/kern/setuid/setresuid.c99
-rw-r--r--regress/sys/kern/setuid/setresuid_effective_exec.c63
-rw-r--r--regress/sys/kern/setuid/setresuid_real_exec.c63
-rw-r--r--regress/sys/kern/setuid/setresuid_saved_exec.c63
-rw-r--r--regress/sys/kern/setuid/setuid.c52
-rw-r--r--regress/sys/kern/setuid/setuid_child.c75
-rw-r--r--regress/sys/kern/setuid/setuid_exec_inherit.c51
-rw-r--r--regress/sys/kern/setuid/setuid_none.c44
-rw-r--r--regress/sys/kern/setuid/setuid_real_exec.c63
-rw-r--r--regress/sys/kern/setuid/setuid_regress.h66
-rw-r--r--regress/sys/kern/setuid/sgidexec.c51
-rw-r--r--regress/sys/kern/setuid/sgidexec_inherit.c51
-rw-r--r--regress/sys/kern/setuid/sgidexec_none.c52
-rw-r--r--regress/sys/kern/setuid/suidexec.c51
-rw-r--r--regress/sys/kern/setuid/suidexec_inherit.c51
-rw-r--r--regress/sys/kern/setuid/suidexec_none.c52
27 files changed, 1702 insertions, 0 deletions
diff --git a/regress/sys/kern/setuid/Makefile b/regress/sys/kern/setuid/Makefile
new file mode 100644
index 00000000000..0e15eca9fc7
--- /dev/null
+++ b/regress/sys/kern/setuid/Makefile
@@ -0,0 +1,115 @@
+# $OpenBSD: Makefile,v 1.1 2014/08/27 07:36:14 blambert Exp $
+
+CFLAGS += -Wall -Wformat -pedantic
+
+REGRESS_TARGETS+= run-regress-setuid_none
+REGRESS_TARGETS+= run-regress-setgid_none
+REGRESS_TARGETS+= run-regress-setuid
+REGRESS_TARGETS+= run-regress-setgid
+REGRESS_TARGETS+= run-regress-seteuid
+REGRESS_TARGETS+= run-regress-setegid
+REGRESS_TARGETS+= run-regress-setuid_child
+REGRESS_TARGETS+= run-regress-setgid_child
+REGRESS_TARGETS+= run-regress-setresuid
+REGRESS_TARGETS+= run-regress-setresgid
+REGRESS_TARGETS+= run-regress-suidexec-on-inherit-on
+REGRESS_TARGETS+= run-regress-suidexec-on-inherit-inherit
+REGRESS_TARGETS+= run-regress-suidexec-off-on-inherit
+REGRESS_TARGETS+= run-regress-suidexec-off-off-on
+REGRESS_TARGETS+= run-regress-sgidexec-on-inherit-on
+REGRESS_TARGETS+= run-regress-sgidexec-on-inherit-inherit
+REGRESS_TARGETS+= run-regress-sgidexec-off-on-inherit
+REGRESS_TARGETS+= run-regress-sgidexec-off-off-on
+REGRESS_TARGETS+= run-regress-suidexec-real-exec-inherit
+REGRESS_TARGETS+= run-regress-suidexec-effective-exec-inherit
+REGRESS_TARGETS+= run-regress-suidexec-saved-exec-inherit
+REGRESS_TARGETS+= run-regress-sgidexec-real-exec-inherit
+REGRESS_TARGETS+= run-regress-sgidexec-effective-exec-inherit
+REGRESS_TARGETS+= run-regress-sgidexec-saved-exec-inherit
+
+CLEANFILES+= *.o
+CLEANFILES+= setuid_none
+CLEANFILES+= setgid_none
+CLEANFILES+= setuid
+CLEANFILES+= setgid
+CLEANFILES+= seteuid
+CLEANFILES+= setegid
+CLEANFILES+= setuid_child
+CLEANFILES+= setgid_child
+CLEANFILES+= setresuid
+CLEANFILES+= setresgid
+CLEANFILES+= setresuid_real_exec
+CLEANFILES+= setresuid_effective_exec
+CLEANFILES+= setresuid_saved_exec
+CLEANFILES+= suidexec_none
+CLEANFILES+= suidexec
+CLEANFILES+= sgidexec
+CLEANFILES+= setresgid_real_exec
+CLEANFILES+= setresgid_effective_exec
+CLEANFILES+= setresgid_saved_exec
+CLEANFILES+= sgidexec_none
+CLEANFILES+= suidexec_inherit
+CLEANFILES+= sgidexec_inherit
+CLEANFILES+= setuid_exec_inherit
+CLEANFILES+= setgid_exec_inherit
+
+run-regress-setuid_none: setuid_none
+ ./setuid_none
+run-regress-setgid_none: setgid_none
+ ./setgid_none
+run-regress-setuid: setuid
+ ${SUDO} ./setuid
+run-regress-setgid: setgid
+ ${SUDO} ./setgid
+run-regress-seteuid: seteuid
+ ${SUDO} ./seteuid
+run-regress-setegid: setegid
+ ${SUDO} ./setegid
+run-regress-setuid_child: setuid_child
+ ${SUDO} ./setuid_child
+run-regress-setgid_child: setgid_child
+ ${SUDO} ./setgid_child
+run-regress-setresuid: setresuid
+ ${SUDO} ./setresuid
+run-regress-setresgid: setresgid
+ ${SUDO} ./setresgid
+
+run-regress-suidexec-on-inherit-on: suidexec-install
+ ${SUDO} ./suidexec ./suidexec_inherit ./suidexec
+run-regress-suidexec-off-on-inherit: suidexec-install
+ ${SUDO} ./suidexec_none ./suidexec ./suidexec_inherit
+run-regress-suidexec-on-inherit-inherit: suidexec-install
+ ${SUDO} ./suidexec ./suidexec_inherit ./suidexec_inherit
+run-regress-suidexec-off-off-on: suidexec-install
+ ${SUDO} ./suidexec_none ./suidexec_none ./suidexec
+run-regress-suidexec-real-exec-inherit: suidexec-install
+ ${SUDO} ./setresuid_real_exec ./setuid_exec_inherit
+run-regress-suidexec-effective-exec-inherit: suidexec-install
+ ${SUDO} ./setresuid_effective_exec ./setuid_exec_inherit
+run-regress-suidexec-saved-exec-inherit: suidexec-install
+ ${SUDO} ./setresuid_saved_exec ./setuid_exec_inherit
+
+run-regress-sgidexec-on-inherit-on: sgidexec-install
+ ${SUDO} ./sgidexec ./sgidexec_inherit ./sgidexec
+run-regress-sgidexec-off-on-inherit: sgidexec-install
+ ${SUDO} ./sgidexec_none ./sgidexec ./sgidexec_inherit
+run-regress-sgidexec-on-inherit-inherit: sgidexec-install
+ ${SUDO} ./sgidexec ./sgidexec_inherit ./sgidexec_inherit
+run-regress-sgidexec-off-off-on: sgidexec-install
+ ${SUDO} ./sgidexec_none ./sgidexec_none ./sgidexec
+run-regress-sgidexec-real-exec-inherit: sgidexec-install
+ ${SUDO} ./setresgid_real_exec ./setgid_exec_inherit
+run-regress-sgidexec-effective-exec-inherit: sgidexec-install
+ ${SUDO} ./setresgid_effective_exec ./setgid_exec_inherit
+run-regress-sgidexec-saved-exec-inherit: sgidexec-install
+ ${SUDO} ./setresgid_saved_exec ./setgid_exec_inherit
+
+suidexec-install: suidexec suidexec_none suidexec_inherit setresuid_real_exec setresuid_effective_exec setresuid_saved_exec setuid_exec_inherit
+ ${SUDO} chown nobody:nobody ./suidexec
+ ${SUDO} chmod 4555 ./suidexec
+
+sgidexec-install: sgidexec sgidexec_none sgidexec_inherit setresgid_real_exec setresgid_effective_exec setresgid_saved_exec setgid_exec_inherit
+ ${SUDO} chown nobody:nobody ./sgidexec
+ ${SUDO} chmod 2555 ./sgidexec
+
+.include <bsd.regress.mk>
diff --git a/regress/sys/kern/setuid/setegid.c b/regress/sys/kern/setuid/setegid.c
new file mode 100644
index 00000000000..e62d0eb7860
--- /dev/null
+++ b/regress/sys/kern/setuid/setegid.c
@@ -0,0 +1,64 @@
+/* $OpenBSD: setegid.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, const char *argv[])
+{
+ struct kinfo_proc kproc;
+ struct passwd *pw;
+ gid_t gid;
+
+ gid = getgid();
+
+ if ((pw = getpwnam(_SETUID_REGRESS_USER)) == NULL)
+ err(1, "unknown user \"%s\"", _SETUID_REGRESS_USER);
+
+ if (setegid(pw->pw_gid) == -1)
+ err(1, "setegid 0");
+
+ if (getegid() != pw->pw_gid)
+ errx(1, "mismatched effective gids");
+
+ /* should only respond to setuid upon exec */
+ if (issetugid())
+ errx(1, "process incorrectly marked as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read 0 failed");
+
+ if (!(kproc.p_psflags & PS_SUGID))
+ errx(1, "PS_SUGID not set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ /* at this point, we should be able to reset our gid */
+ if (setegid(gid) == -1)
+ err(1, "setegid 1");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read 0 failed");
+
+ if (!(kproc.p_psflags & PS_SUGID))
+ errx(1, "PS_SUGID not set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/seteuid.c b/regress/sys/kern/setuid/seteuid.c
new file mode 100644
index 00000000000..7da65acb307
--- /dev/null
+++ b/regress/sys/kern/setuid/seteuid.c
@@ -0,0 +1,66 @@
+/* $OpenBSD: seteuid.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, const char *argv[])
+{
+ struct kinfo_proc kproc;
+ struct passwd *pw;
+ uid_t uid;
+
+ uid = getuid();
+
+ if ((pw = getpwnam(_SETUID_REGRESS_USER)) == NULL)
+ err(1, "unknown user \"%s\"", _SETUID_REGRESS_USER);
+
+ if (seteuid(pw->pw_uid) == -1)
+ err(1, "seteuid 0");
+
+ if (geteuid() != pw->pw_uid)
+ errx(1, "mismatched effective uids");
+
+ checkuids(uid, pw->pw_uid, uid, "seteuid");
+
+ /* should only respond to setuid upon exec */
+ if (issetugid())
+ errx(1, "process incorrectly marked as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read 0 failed");
+
+ if (!(kproc.p_psflags & PS_SUGID))
+ errx(1, "PS_SUGID not set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ /* at this point, we should be able to reset our uid */
+ if (seteuid(uid) == -1)
+ err(1, "seteuid 1");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read 1 failed");
+
+ if (!(kproc.p_psflags & PS_SUGID))
+ errx(1, "PS_SUGID not set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/setgid.c b/regress/sys/kern/setuid/setgid.c
new file mode 100644
index 00000000000..ee2b04a5cf1
--- /dev/null
+++ b/regress/sys/kern/setuid/setgid.c
@@ -0,0 +1,52 @@
+/* $OpenBSD: setgid.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, const char *argv[])
+{
+ struct kinfo_proc kproc;
+ struct passwd *pw;
+
+ if ((pw = getpwnam(_SETUID_REGRESS_USER)) == NULL)
+ err(1, "unknown user \"%s\"", _SETUID_REGRESS_USER);
+
+ /*
+ * From the setgid man page:
+ * The setgid() function sets the real and effective group IDs
+ * and the saved set-group-ID of the current process
+ */
+ if (setgid(pw->pw_gid) == -1)
+ err(1, "setgid");
+ checkgids(pw->pw_gid, pw->pw_gid, pw->pw_gid, "setgid");
+
+ /* should only respond to setuid upon exec */
+ if (issetugid())
+ errx(1, "process incorrectly marked as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (!(kproc.p_psflags & PS_SUGID))
+ errx(1, "PS_SUGID not set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/setgid_child.c b/regress/sys/kern/setuid/setgid_child.c
new file mode 100644
index 00000000000..982e2057d2c
--- /dev/null
+++ b/regress/sys/kern/setuid/setgid_child.c
@@ -0,0 +1,75 @@
+/* $OpenBSD: setgid_child.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, const char *argv[])
+{
+ struct kinfo_proc kproc;
+ struct passwd *pw;
+ pid_t pid;
+ int status;
+
+ if ((pw = getpwnam(_SETUID_REGRESS_USER)) == NULL)
+ err(1, "unknown user \"%s\"", _SETUID_REGRESS_USER);
+
+ if (setgid(pw->pw_gid) == -1)
+ err(1, "setgid");
+
+ switch ((pid = fork())) {
+
+ default:
+ waitpid(pid, &status, 0);
+ if (WIFSIGNALED(status))
+ errx(1, "child exited due to signal %d",
+ WTERMSIG(status));
+ else if (WEXITSTATUS(status) != 0)
+ errx(1, "child exited with status %d",
+ WEXITSTATUS(status));
+ break;
+
+ case 0:
+ /*
+ * From the setgid man page:
+ * The setgid() function sets the real and effective user IDs
+ * and the saved set-user-ID of the current process
+ */
+ checkgids(pw->pw_gid, pw->pw_gid, pw->pw_gid, "setgid child");
+
+ /* should only respond to setgid upon exec */
+ if (issetugid())
+ errx(1, "child incorrectly marked as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (!(kproc.p_psflags & PS_SUGID))
+ errx(1, "PS_SUGID not set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ break;
+
+ case -1:
+ err(1, "fork");
+ /* NOTREACHED */
+ }
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/setgid_exec_inherit.c b/regress/sys/kern/setuid/setgid_exec_inherit.c
new file mode 100644
index 00000000000..6074c488ca7
--- /dev/null
+++ b/regress/sys/kern/setuid/setgid_exec_inherit.c
@@ -0,0 +1,51 @@
+/* $OpenBSD: setgid_exec_inherit.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, char *argv[])
+{
+ struct kinfo_proc kproc;
+ char *toexec = NULL;
+
+ if (argc > 1) {
+ argv++;
+ if ((toexec = strdup(argv[0])) == NULL)
+ err(1, "strdup");
+ }
+
+ if (!issetugid())
+ errx(1, "process not marked as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (kproc.p_psflags & PS_SUGID)
+ errx(1, "PS_SUGID incorrectly set");
+ if (!(kproc.p_psflags & PS_SUGIDEXEC))
+ errx(1, "PS_SUGIDEXEC not set");
+
+ if (toexec != NULL)
+ if (execv(toexec, argv) == -1)
+ err(1, "exec of %s failed", toexec);
+ free(toexec);
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/setgid_none.c b/regress/sys/kern/setuid/setgid_none.c
new file mode 100644
index 00000000000..6f3d9a7cfd0
--- /dev/null
+++ b/regress/sys/kern/setuid/setgid_none.c
@@ -0,0 +1,44 @@
+/* $OpenBSD: setgid_none.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, const char *argv[])
+{
+ struct kinfo_proc kproc;
+ gid_t gid;
+
+ gid = getgid();
+
+ checkgids(gid, gid, gid, "checkgid");
+
+ /* should only respond to setgid upon exec */
+ if (issetugid())
+ errx(1, "process incorrectly marked as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (kproc.p_psflags & PS_SUGID)
+ errx(1, "PS_SUGID incorrectly set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/setresgid.c b/regress/sys/kern/setuid/setresgid.c
new file mode 100644
index 00000000000..a295d3609f5
--- /dev/null
+++ b/regress/sys/kern/setuid/setresgid.c
@@ -0,0 +1,102 @@
+/* $OpenBSD: setresgid.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, const char *argv[])
+{
+ struct kinfo_proc kproc;
+ struct passwd *pw;
+ gid_t gid;
+
+ if ((pw = getpwnam(_SETUID_REGRESS_USER)) == NULL)
+ err(1, "unknown user \"%s\"", _SETUID_REGRESS_USER);
+
+ gid = getgid();
+
+ if (setresgid(pw->pw_gid, -1, -1) == -1)
+ err(1, "setgid 0");
+ checkgids(pw->pw_gid, gid, gid, "0");
+
+ /* should only respond to setgid upon exec */
+ if (issetugid())
+ errx(1, "process incorrectly marked as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (!(kproc.p_psflags & PS_SUGID))
+ errx(1, "PS_SUGID not set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ /* we should be able to roll back our gids for now */
+ if (setresgid(gid, -1, -1) == -1)
+ err(1, "setgid 1");
+ checkgids(gid, gid, gid, "1");
+
+ if (setresgid(-1, pw->pw_gid, -1) == -1)
+ err(1, "setgid 2");
+ checkgids(gid, pw->pw_gid, gid, "2");
+
+ /* we should be able to roll back our gids for now */
+ if (setresgid(-1, gid, -1) == -1)
+ err(1, "setgid 3");
+ checkgids(gid, gid, gid, "3");
+
+ /*
+ * after changing our saved gid and dropping superuser privs,
+ * we should be able to change our real and effective gids to
+ * that of our saved gid, but not to anything else
+ */
+
+ if (setresgid(-1, -1, pw->pw_gid) == -1)
+ err(1, "setgid 4");
+ checkgids(gid, gid, pw->pw_gid, "4");
+
+ if (setresuid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1)
+ err(1, "setresuid 4");
+
+ if (setresgid(pw->pw_gid, -1, -1) == -1)
+ err(1, "setgid 5");
+ checkgids(pw->pw_gid, gid, pw->pw_gid, "5");
+
+ if (setresgid(-1, pw->pw_gid, -1) == -1)
+ err(1, "setgid 6");
+ checkgids(pw->pw_gid, pw->pw_gid, pw->pw_gid, "6");
+
+ if (setresgid(gid, -1, -1) != -1)
+ errx(1, "incorrectly capable of setting real gid");
+ checkgids(pw->pw_gid, pw->pw_gid, pw->pw_gid, "7");
+
+ if (setresgid(-1, gid, -1) != -1)
+ errx(1, "incorrectly capable of setting effective gid");
+ checkgids(pw->pw_gid, pw->pw_gid, pw->pw_gid, "9");
+
+ if (setresgid(-1, -1, gid) != -1)
+ errx(1, "incorrectly capable of setting saved gid");
+ checkgids(pw->pw_gid, pw->pw_gid, pw->pw_gid, "9");
+
+ /* sanity-check use of -1 as noop */
+ if (setresgid(-1, -1, -1) == -1)
+ errx(1, "-1 not properly recognized as noop");
+ checkgids(pw->pw_gid, pw->pw_gid, pw->pw_gid, "9");
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/setresgid_effective_exec.c b/regress/sys/kern/setuid/setresgid_effective_exec.c
new file mode 100644
index 00000000000..33767fa8bd3
--- /dev/null
+++ b/regress/sys/kern/setuid/setresgid_effective_exec.c
@@ -0,0 +1,62 @@
+/* $OpenBSD: setresgid_effective_exec.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, char *argv[])
+{
+ struct kinfo_proc kproc;
+ struct passwd *pw;
+ char *toexec = NULL;
+ gid_t gid;
+
+ if (argc > 1) {
+ argv++;
+ if ((toexec = strdup(argv[0])) == NULL)
+ err(1, "strdup");
+ }
+
+ gid = getgid();
+
+ if ((pw = getpwnam(_SETUID_REGRESS_USER)) == NULL)
+ err(1, "unknown user \"%s\"", _SETUID_REGRESS_USER);
+
+ if (setresgid(-1, pw->pw_gid, -1) == -1)
+ err(1, "setgid");
+ checkgids(gid, pw->pw_gid, gid, "setgid");
+
+ if (issetugid())
+ errx(1, "process incorrectly marked as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (!(kproc.p_psflags & PS_SUGID))
+ errx(1, "PS_SUGID not set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ if (toexec != NULL)
+ if (execv(toexec, argv) == -1)
+ err(1, "exec of %s failed", toexec);
+ free(toexec);
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/setresgid_real_exec.c b/regress/sys/kern/setuid/setresgid_real_exec.c
new file mode 100644
index 00000000000..fd9b9d32c20
--- /dev/null
+++ b/regress/sys/kern/setuid/setresgid_real_exec.c
@@ -0,0 +1,62 @@
+/* $OpenBSD: setresgid_real_exec.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, char *argv[])
+{
+ struct kinfo_proc kproc;
+ struct passwd *pw;
+ char *toexec = NULL;
+ gid_t gid;
+
+ if (argc > 1) {
+ argv++;
+ if ((toexec = strdup(argv[0])) == NULL)
+ err(1, "strdup");
+ }
+
+ gid = getgid();
+
+ if ((pw = getpwnam(_SETUID_REGRESS_USER)) == NULL)
+ err(1, "unknown user \"%s\"", _SETUID_REGRESS_USER);
+
+ if (setresgid(pw->pw_gid, -1, -1) == -1)
+ err(1, "setgid");
+ checkgids(pw->pw_gid, gid, gid, "setgid");
+
+ if (issetugid())
+ errx(1, "process incorrectly marked as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (!(kproc.p_psflags & PS_SUGID))
+ errx(1, "PS_SUGID not set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ if (toexec != NULL)
+ if (execv(toexec, argv) == -1)
+ err(1, "exec of %s failed", toexec);
+ free(toexec);
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/setresgid_saved_exec.c b/regress/sys/kern/setuid/setresgid_saved_exec.c
new file mode 100644
index 00000000000..f1f6bf0cfd3
--- /dev/null
+++ b/regress/sys/kern/setuid/setresgid_saved_exec.c
@@ -0,0 +1,62 @@
+/* $OpenBSD: setresgid_saved_exec.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, char *argv[])
+{
+ struct kinfo_proc kproc;
+ struct passwd *pw;
+ char *toexec = NULL;
+ gid_t gid;
+
+ if (argc > 1) {
+ argv++;
+ if ((toexec = strdup(argv[0])) == NULL)
+ err(1, "strdup");
+ }
+
+ gid = getgid();
+
+ if ((pw = getpwnam(_SETUID_REGRESS_USER)) == NULL)
+ err(1, "unknown user \"%s\"", _SETUID_REGRESS_USER);
+
+ if (setresgid(-1, -1, pw->pw_gid) == -1)
+ err(1, "setgid");
+ checkgids(gid, gid, pw->pw_gid, "setgid");
+
+ if (issetugid())
+ errx(1, "process incorrectly marked as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (!(kproc.p_psflags & PS_SUGID))
+ errx(1, "PS_SUGID not set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ if (toexec != NULL)
+ if (execv(toexec, argv) == -1)
+ err(1, "exec of %s failed", toexec);
+ free(toexec);
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/setresuid.c b/regress/sys/kern/setuid/setresuid.c
new file mode 100644
index 00000000000..0721d254482
--- /dev/null
+++ b/regress/sys/kern/setuid/setresuid.c
@@ -0,0 +1,99 @@
+/* $OpenBSD: setresuid.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, const char *argv[])
+{
+ struct kinfo_proc kproc;
+ struct passwd *pw;
+ uid_t uid;
+
+ if ((pw = getpwnam(_SETUID_REGRESS_USER)) == NULL)
+ err(1, "unknown user \"%s\"", _SETUID_REGRESS_USER);
+
+ uid = getuid();
+
+ if (setresuid(pw->pw_uid, -1, -1) == -1)
+ err(1, "setuid 0");
+ checkuids(pw->pw_uid, uid, uid, "0");
+
+ /* should only respond to setuid upon exec */
+ if (issetugid())
+ errx(1, "process incorrectly marked as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (!(kproc.p_psflags & PS_SUGID))
+ errx(1, "PS_SUGID not set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ /* we should be able to roll back our uids for now */
+ if (setresuid(uid, -1, -1) == -1)
+ err(1, "setuid 1");
+ checkuids(uid, uid, uid, "1");
+
+ if (setresuid(-1, pw->pw_uid, -1) == -1)
+ err(1, "setuid 2");
+ checkuids(uid, pw->pw_uid, uid, "2");
+
+ /* we should be able to roll back our uids for now */
+ if (setresuid(-1, uid, -1) == -1)
+ err(1, "setuid 3");
+ checkuids(uid, uid, uid, "3");
+
+ /*
+ * after changing our saved uid, we should be able to change
+ * our real and effective uids to that of our saved uid,
+ * but not to anything else
+ */
+
+ if (setresuid(-1, -1, pw->pw_uid) == -1)
+ err(1, "setuid 4");
+ checkuids(uid, uid, pw->pw_uid, "4");
+
+ if (setresuid(pw->pw_uid, -1, -1) == -1)
+ err(1, "setuid 5");
+ checkuids(pw->pw_uid, uid, pw->pw_uid, "5");
+
+ if (setresuid(-1, pw->pw_uid, -1) == -1)
+ err(1, "setuid 6");
+ checkuids(pw->pw_uid, pw->pw_uid, pw->pw_uid, "6");
+
+ if (setresuid(uid, -1, -1) != -1)
+ errx(1, "incorrectly capable of setting real uid");
+ checkuids(pw->pw_uid, pw->pw_uid, pw->pw_uid, "7");
+
+ if (setresuid(-1, uid, -1) != -1)
+ errx(1, "incorrectly capable of setting effective uid");
+ checkuids(pw->pw_uid, pw->pw_uid, pw->pw_uid, "9");
+
+ if (setresuid(-1, -1, uid) != -1)
+ errx(1, "incorrectly capable of setting saved uid");
+ checkuids(pw->pw_uid, pw->pw_uid, pw->pw_uid, "9");
+
+ /* sanity-check use of -1 as noop */
+ if (setresuid(-1, -1, -1) == -1)
+ errx(1, "-1 not properly recognized as noop");
+ checkuids(pw->pw_uid, pw->pw_uid, pw->pw_uid, "9");
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/setresuid_effective_exec.c b/regress/sys/kern/setuid/setresuid_effective_exec.c
new file mode 100644
index 00000000000..860a47ef519
--- /dev/null
+++ b/regress/sys/kern/setuid/setresuid_effective_exec.c
@@ -0,0 +1,63 @@
+/* $OpenBSD: setresuid_effective_exec.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, char *argv[])
+{
+ struct kinfo_proc kproc;
+ struct passwd *pw;
+ char *toexec = NULL;
+ uid_t uid;
+
+ if (argc > 1) {
+ argv ++;
+ if ((toexec = strdup(argv[0])) == NULL)
+ err(1, "strdup");
+ }
+
+ if ((pw = getpwnam(_SETUID_REGRESS_USER)) == NULL)
+ err(1, "unknown user \"%s\"", _SETUID_REGRESS_USER);
+
+ uid = getuid();
+
+ if (setresuid(-1, pw->pw_uid, -1) == -1)
+ err(1, "setuid");
+ checkuids(uid, pw->pw_uid, uid, "setuid");
+
+ /* should only respond to setuid upon exec */
+ if (issetugid())
+ errx(1, "process incorrectly as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (!(kproc.p_psflags & PS_SUGID))
+ errx(1, "PS_SUGID not set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ if (toexec != NULL)
+ if (execv(toexec, argv) == -1)
+ err(1, "exec of %s failed", toexec);
+ free(toexec);
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/setresuid_real_exec.c b/regress/sys/kern/setuid/setresuid_real_exec.c
new file mode 100644
index 00000000000..18fff09291e
--- /dev/null
+++ b/regress/sys/kern/setuid/setresuid_real_exec.c
@@ -0,0 +1,63 @@
+/* $OpenBSD: setresuid_real_exec.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, char *argv[])
+{
+ struct kinfo_proc kproc;
+ struct passwd *pw;
+ char *toexec = NULL;
+ uid_t uid;
+
+ if (argc > 1) {
+ argv ++;
+ if ((toexec = strdup(argv[0])) == NULL)
+ err(1, "strdup");
+ }
+
+ if ((pw = getpwnam(_SETUID_REGRESS_USER)) == NULL)
+ err(1, "unknown user \"%s\"", _SETUID_REGRESS_USER);
+
+ uid = getuid();
+
+ if (setresuid(pw->pw_uid, -1, -1) == -1)
+ err(1, "setuid");
+ checkuids(pw->pw_uid, uid, uid, "setuid");
+
+ /* should only respond to setuid upon exec */
+ if (issetugid())
+ errx(1, "process incorrectly as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (!(kproc.p_psflags & PS_SUGID))
+ errx(1, "PS_SUGID not set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ if (toexec != NULL)
+ if (execv(toexec, argv) == -1)
+ err(1, "exec of %s failed", toexec);
+ free(toexec);
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/setresuid_saved_exec.c b/regress/sys/kern/setuid/setresuid_saved_exec.c
new file mode 100644
index 00000000000..9d76fccbb07
--- /dev/null
+++ b/regress/sys/kern/setuid/setresuid_saved_exec.c
@@ -0,0 +1,63 @@
+/* $OpenBSD: setresuid_saved_exec.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, char *argv[])
+{
+ struct kinfo_proc kproc;
+ struct passwd *pw;
+ char *toexec = NULL;
+ uid_t uid;
+
+ if (argc > 1) {
+ argv ++;
+ if ((toexec = strdup(argv[0])) == NULL)
+ err(1, "strdup");
+ }
+
+ if ((pw = getpwnam(_SETUID_REGRESS_USER)) == NULL)
+ err(1, "unknown user \"%s\"", _SETUID_REGRESS_USER);
+
+ uid = getuid();
+
+ if (setresuid(-1, -1, pw->pw_uid) == -1)
+ err(1, "setuid");
+ checkuids(uid, uid, pw->pw_uid, "setuid");
+
+ /* should only respond to setuid upon exec */
+ if (issetugid())
+ errx(1, "process incorrectly as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (!(kproc.p_psflags & PS_SUGID))
+ errx(1, "PS_SUGID not set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ if (toexec != NULL)
+ if (execv(toexec, argv) == -1)
+ err(1, "exec of %s failed", toexec);
+ free(toexec);
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/setuid.c b/regress/sys/kern/setuid/setuid.c
new file mode 100644
index 00000000000..79ecc57f136
--- /dev/null
+++ b/regress/sys/kern/setuid/setuid.c
@@ -0,0 +1,52 @@
+/* $OpenBSD: setuid.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, const char *argv[])
+{
+ struct kinfo_proc kproc;
+ struct passwd *pw;
+
+ if ((pw = getpwnam(_SETUID_REGRESS_USER)) == NULL)
+ err(1, "unknown user \"%s\"", _SETUID_REGRESS_USER);
+
+ /*
+ * From the setuid man page:
+ * The setuid() function sets the real and effective user IDs
+ * and the saved set-user-ID of the current process
+ */
+ if (setuid(pw->pw_uid) == -1)
+ err(1, "setuid");
+ checkuids(pw->pw_uid, pw->pw_uid, pw->pw_uid, "getresuid");
+
+ /* should only respond to setuid upon exec */
+ if (issetugid())
+ errx(1, "process incorrectly marked as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (!(kproc.p_psflags & PS_SUGID))
+ errx(1, "PS_SUGID not set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/setuid_child.c b/regress/sys/kern/setuid/setuid_child.c
new file mode 100644
index 00000000000..eed09ba09c2
--- /dev/null
+++ b/regress/sys/kern/setuid/setuid_child.c
@@ -0,0 +1,75 @@
+/* $OpenBSD: setuid_child.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, const char *argv[])
+{
+ struct kinfo_proc kproc;
+ struct passwd *pw;
+ pid_t pid;
+ int status;
+
+ if ((pw = getpwnam(_SETUID_REGRESS_USER)) == NULL)
+ err(1, "unknown user \"%s\"", _SETUID_REGRESS_USER);
+
+ if (setuid(pw->pw_uid) == -1)
+ err(1, "setuid");
+
+ switch ((pid = fork())) {
+
+ default:
+ waitpid(pid, &status, 0);
+ if (WIFSIGNALED(status))
+ errx(1, "child exited due to signal %d",
+ WTERMSIG(status));
+ else if (WEXITSTATUS(status) != 0)
+ errx(1, "child exited with status %d",
+ WEXITSTATUS(status));
+ break;
+
+ case 0:
+ /*
+ * From the setuid man page:
+ * The setuid() function sets the real and effective user IDs
+ * and the saved set-user-ID of the current process
+ */
+ checkuids(pw->pw_uid, pw->pw_uid, pw->pw_uid, "setuid child");
+
+ /* should only respond to setuid upon exec */
+ if (issetugid())
+ errx(1, "child incorrectly marked as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (!(kproc.p_psflags & PS_SUGID))
+ errx(1, "PS_SUGID not set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ break;
+
+ case -1:
+ err(1, "fork");
+ /* NOTREACHED */
+ }
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/setuid_exec_inherit.c b/regress/sys/kern/setuid/setuid_exec_inherit.c
new file mode 100644
index 00000000000..b2bd33a2f12
--- /dev/null
+++ b/regress/sys/kern/setuid/setuid_exec_inherit.c
@@ -0,0 +1,51 @@
+/* $OpenBSD: setuid_exec_inherit.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, char *argv[])
+{
+ struct kinfo_proc kproc;
+ char *toexec = NULL;
+
+ if (argc > 1) {
+ argv++;
+ if ((toexec = strdup(argv[0])) == NULL)
+ err(1, "strdup");
+ }
+
+ if (!issetugid())
+ errx(1, "process not marked as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (kproc.p_psflags & PS_SUGID)
+ errx(1, "PS_SUGID incorrectly set");
+ if (!(kproc.p_psflags & PS_SUGIDEXEC))
+ errx(1, "PS_SUGIDEXEC not set");
+
+ if (toexec != NULL)
+ if (execv(toexec, argv) == -1)
+ err(1, "exec of %s failed", toexec);
+ free(toexec);
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/setuid_none.c b/regress/sys/kern/setuid/setuid_none.c
new file mode 100644
index 00000000000..4c13366d0b6
--- /dev/null
+++ b/regress/sys/kern/setuid/setuid_none.c
@@ -0,0 +1,44 @@
+/* $OpenBSD: setuid_none.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, char *argv[])
+{
+ struct kinfo_proc kproc;
+ uid_t uid;
+
+ uid = getuid();
+
+ checkuids(uid, uid, uid, "getuid");
+
+ /* should only respond to setuid upon exec */
+ if (issetugid())
+ errx(1, "process incorrectly marked as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (kproc.p_psflags & PS_SUGID)
+ errx(1, "PS_SUGID incorrectly set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/setuid_real_exec.c b/regress/sys/kern/setuid/setuid_real_exec.c
new file mode 100644
index 00000000000..2b0d73ed0fb
--- /dev/null
+++ b/regress/sys/kern/setuid/setuid_real_exec.c
@@ -0,0 +1,63 @@
+/* $OpenBSD: setuid_real_exec.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, char *argv[])
+{
+ struct kinfo_proc kproc;
+ struct passwd *pw;
+ char *toexec = NULL;
+ uid_t uid;
+
+ if (argc > 1) {
+ argv ++;
+ if ((toexec = strdup(argv[0])) == NULL)
+ err(1, "strdup");
+ }
+
+ if ((pw = getpwnam(_SETUID_REGRESS_USER)) == NULL)
+ err(1, "unknown user \"%s\"", _SETUID_REGRESS_USER);
+
+ uid = getuid();
+
+ if (setresuid(pw->pw_uid, -1, -1) == -1)
+ err(1, "setuid");
+ checkuids(pw->pw_uid, uid, uid, "setuid");
+
+ /* should only respond to setuid upon exec */
+ if (issetugid())
+ errx(1, "process incorrectly as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (!(kproc.p_psflags & PS_SUGID))
+ errx(1, "PS_SUGID not set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ if (toexec != NULL)
+ if (execv(toexec, argv) == -1)
+ err(1, "exec of %s failed", toexec);
+ free(toexec);
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/setuid_regress.h b/regress/sys/kern/setuid/setuid_regress.h
new file mode 100644
index 00000000000..655c6aae757
--- /dev/null
+++ b/regress/sys/kern/setuid/setuid_regress.h
@@ -0,0 +1,66 @@
+/* $OpenBSD: setuid_regress.h,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#ifndef _SETUID_REGRESS_H_
+#define _SETUID_REGRESS_H_
+
+#define _SETUID_REGRESS_USER "nobody"
+
+static inline int
+read_kproc_pid(struct kinfo_proc *kproc, pid_t pid)
+{
+ int args[6];
+ size_t size;
+
+ args[0] = CTL_KERN;
+ args[1] = KERN_PROC;
+ args[2] = KERN_PROC_PID;
+ args[3] = pid;
+ args[4] = sizeof(*kproc);
+ args[5] = 1;
+
+ size = sizeof(*kproc);
+ return (sysctl(args, 6, kproc, &size, NULL, 0));
+}
+
+static inline void
+checkuids(uid_t truid, uid_t teuid, uid_t tsuid, const char *str)
+{
+ uid_t ruid, euid, suid;
+
+ if (getresuid(&ruid, &euid, &suid) == -1)
+ err(1, "getresuid %s", str);
+
+ if (ruid != truid)
+ errx(1, "real uid incorrectly set %s: is %u should be %u",
+ str, ruid, truid);
+ if (euid != teuid)
+ errx(1, "effective uid incorrectly set %s: is %u should be %u",
+ str, euid, teuid);
+ if (suid != tsuid)
+ errx(1, "saved uid incorrectly set %s: is %u should be %u",
+ str, suid, tsuid);
+}
+
+void
+checkgids(gid_t trgid, gid_t tegid, gid_t tsgid, const char *str)
+{
+ gid_t rgid, egid, sgid;
+
+ if (getresgid(&rgid, &egid, &sgid) == -1)
+ err(1, "getresgid %s", str);
+
+ if (rgid != trgid)
+ errx(1, "real gid incorrectly set %s: is %u should be %u",
+ str, rgid, trgid);
+ if (egid != tegid)
+ errx(1, "effective gid incorrectly set %s: is %u should be %u",
+ str, egid, tegid);
+ if (sgid != tsgid)
+ errx(1, "saved gid incorrectly set %s: is %u should be %u",
+ str, sgid, tsgid);
+}
+#endif
diff --git a/regress/sys/kern/setuid/sgidexec.c b/regress/sys/kern/setuid/sgidexec.c
new file mode 100644
index 00000000000..094e312b148
--- /dev/null
+++ b/regress/sys/kern/setuid/sgidexec.c
@@ -0,0 +1,51 @@
+/* $OpenBSD: sgidexec.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, char *argv[])
+{
+ struct kinfo_proc kproc;
+ char *toexec = NULL;
+
+ if (argc > 1) {
+ argv++;
+ if ((toexec = strdup(argv[0])) == NULL)
+ err(1, "strdup");
+ }
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (issetugid() != 1)
+ errx(1, "process not marked as issetugid()");
+
+ if (!(kproc.p_psflags & PS_SUGID))
+ errx(1, "PS_SUGID not set");
+ if (!(kproc.p_psflags & PS_SUGIDEXEC))
+ errx(1, "PS_SUGIDEXEC not set");
+
+ if (toexec != NULL)
+ if (execv(toexec, argv) == -1)
+ err(1, "exec of %s failed", toexec);
+ free(toexec);
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/sgidexec_inherit.c b/regress/sys/kern/setuid/sgidexec_inherit.c
new file mode 100644
index 00000000000..0d4bec3edbb
--- /dev/null
+++ b/regress/sys/kern/setuid/sgidexec_inherit.c
@@ -0,0 +1,51 @@
+/* $OpenBSD: sgidexec_inherit.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, char *argv[])
+{
+ struct kinfo_proc kproc;
+ char *toexec = NULL;
+
+ if (argc > 1) {
+ argv++;
+ if ((toexec = strdup(argv[0])) == NULL)
+ err(1, "strdup");
+ }
+
+ if (!issetugid())
+ errx(1, "process not marked as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (kproc.p_psflags & PS_SUGID)
+ errx(1, "PS_SUGID incorrectly set");
+ if (!(kproc.p_psflags & PS_SUGIDEXEC))
+ errx(1, "PS_SUGIDEXEC not set");
+
+ if (toexec != NULL)
+ if (execv(toexec, argv) == -1)
+ err(1, "exec of %s failed", toexec);
+ free(toexec);
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/sgidexec_none.c b/regress/sys/kern/setuid/sgidexec_none.c
new file mode 100644
index 00000000000..f189ac24ac9
--- /dev/null
+++ b/regress/sys/kern/setuid/sgidexec_none.c
@@ -0,0 +1,52 @@
+/* $OpenBSD: sgidexec_none.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, char *argv[])
+{
+ struct kinfo_proc kproc;
+ char *toexec = NULL;
+
+ if (argc > 1) {
+ argv++;
+ if ((toexec = strdup(argv[0])) == NULL)
+ err(1, "strdup");
+ }
+
+ /* should only respond to setgid upon exec */
+ if (issetugid())
+ errx(1, "process incorrectly marked as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (kproc.p_psflags & PS_SUGID)
+ errx(1, "PS_SUGID not set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ if (toexec != NULL)
+ if (execv(toexec, argv) == -1)
+ err(1, "exec of %s failed", toexec);
+ free(toexec);
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/suidexec.c b/regress/sys/kern/setuid/suidexec.c
new file mode 100644
index 00000000000..0503aecc8bd
--- /dev/null
+++ b/regress/sys/kern/setuid/suidexec.c
@@ -0,0 +1,51 @@
+/* $OpenBSD: suidexec.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, char *argv[])
+{
+ struct kinfo_proc kproc;
+ char *toexec = NULL;
+
+ if (argc > 1) {
+ argv++;
+ if ((toexec = strdup(argv[0])) == NULL)
+ err(1, "strdup");
+ }
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (!issetugid())
+ errx(1, "process not marked as issetugid()");
+
+ if (!(kproc.p_psflags & PS_SUGID))
+ errx(1, "PS_SUGID not set");
+ if (!(kproc.p_psflags & PS_SUGIDEXEC))
+ errx(1, "PS_SUGIDEXEC not set");
+
+ if (toexec != NULL)
+ if (execv(toexec, argv) == -1)
+ err(1, "exec of %s failed", toexec);
+ free(toexec);
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/suidexec_inherit.c b/regress/sys/kern/setuid/suidexec_inherit.c
new file mode 100644
index 00000000000..e6db0ece21b
--- /dev/null
+++ b/regress/sys/kern/setuid/suidexec_inherit.c
@@ -0,0 +1,51 @@
+/* $OpenBSD: suidexec_inherit.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, char *argv[])
+{
+ struct kinfo_proc kproc;
+ char *toexec = NULL;
+
+ if (argc > 1) {
+ argv++;
+ if ((toexec = strdup(argv[0])) == NULL)
+ err(1, "strdup");
+ }
+
+ if (!issetugid())
+ errx(1, "process not marked as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (kproc.p_psflags & PS_SUGID)
+ errx(1, "PS_SUGID incorrectly set");
+ if (!(kproc.p_psflags & PS_SUGIDEXEC))
+ errx(1, "PS_SUGIDEXEC not set");
+
+ if (toexec != NULL)
+ if (execv(toexec, argv) == -1)
+ err(1, "exec of %s failed", toexec);
+ free(toexec);
+
+ exit(0);
+}
diff --git a/regress/sys/kern/setuid/suidexec_none.c b/regress/sys/kern/setuid/suidexec_none.c
new file mode 100644
index 00000000000..95fad6c05c4
--- /dev/null
+++ b/regress/sys/kern/setuid/suidexec_none.c
@@ -0,0 +1,52 @@
+/* $OpenBSD: suidexec_none.c,v 1.1 2014/08/27 07:36:14 blambert Exp $ */
+/*
+ * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "setuid_regress.h"
+
+int
+main(int argc, char *argv[])
+{
+ struct kinfo_proc kproc;
+ char *toexec = NULL;
+
+ if (argc > 1) {
+ argv++;
+ if ((toexec = strdup(argv[0])) == NULL)
+ err(1, "strdup");
+ }
+
+ /* should only respond to setuid upon exec */
+ if (issetugid())
+ errx(1, "process incorrectly marked as issetugid()");
+
+ if (read_kproc_pid(&kproc, getpid()) == -1)
+ err(1, "kproc read failed");
+
+ if (kproc.p_psflags & PS_SUGID)
+ errx(1, "PS_SUGID not set");
+ if (kproc.p_psflags & PS_SUGIDEXEC)
+ errx(1, "PS_SUGIDEXEC incorrectly set");
+
+ if (toexec != NULL)
+ if (execv(toexec, argv) == -1)
+ err(1, "exec of %s failed", toexec);
+ free(toexec);
+
+ exit(0);
+}