1 /* $OpenBSD: setuid_child.c,v 1.3 2021/12/15 18:42:38 anton Exp $ */
2 /*
3 * Written by Bret Stephen Lambert <blambert@openbsd.org> 2014
4 * Public Domain.
5 */
6
7 #include <sys/types.h>
8 #include <sys/signal.h>
9 #include <sys/proc.h>
10 #include <sys/sysctl.h>
11 #include <sys/wait.h>
12
13 #include <err.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <pwd.h>
17 #include <unistd.h>
18
19 #include "setuid_regress.h"
20
21 int
main(int argc,const char * argv[])22 main(int argc, const char *argv[])
23 {
24 struct kinfo_proc kproc;
25 struct passwd *pw;
26 pid_t pid;
27 int status;
28
29 if ((pw = getpwnam(_SETUID_REGRESS_USER)) == NULL)
30 err(1, "unknown user \"%s\"", _SETUID_REGRESS_USER);
31
32 if (setuid(pw->pw_uid) == -1)
33 err(1, "setuid");
34
35 switch ((pid = fork())) {
36
37 default:
38 waitpid(pid, &status, 0);
39 if (WIFSIGNALED(status))
40 errx(1, "child exited due to signal %d",
41 WTERMSIG(status));
42 else if (WEXITSTATUS(status) != 0)
43 errx(1, "child exited with status %d",
44 WEXITSTATUS(status));
45 break;
46
47 case 0:
48 /*
49 * From the setuid man page:
50 * The setuid() function sets the real and effective user IDs
51 * and the saved set-user-ID of the current process
52 */
53 checkuids(pw->pw_uid, pw->pw_uid, pw->pw_uid, "setuid child");
54
55 /* should only respond to setuid upon exec */
56 if (issetugid())
57 errx(1, "child incorrectly marked as issetugid()");
58
59 if (read_kproc_pid(&kproc, getpid()) == -1)
60 err(1, "kproc read failed");
61
62 if (!(kproc.p_psflags & PS_SUGID))
63 errx(1, "PS_SUGID not set");
64 if (kproc.p_psflags & PS_SUGIDEXEC)
65 errx(1, "PS_SUGIDEXEC incorrectly set");
66
67 break;
68
69 case -1:
70 err(1, "fork");
71 /* NOTREACHED */
72 }
73
74 exit(0);
75 }
76