Bug Summary

File:src/libexec/rpc.rstatd/rstatd.c
Warning:line 83, column 2
The return value from the call to 'setegid' is not checked. If an error occurs in 'setegid', the following code may execute with unexpected privileges

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name rstatd.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/libexec/rpc.rstatd/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/libexec/rpc.rstatd/../../usr.bin/vmstat -D NOKVM -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/libexec/rpc.rstatd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/libexec/rpc.rstatd/rstatd.c
1/* $OpenBSD: rstatd.c,v 1.31 2023/03/08 04:43:05 guenther Exp $ */
2
3/*-
4 * Copyright (c) 1993, John Brezak
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <sys/types.h>
32#include <sys/socket.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <unistd.h>
37#include <limits.h>
38#include <signal.h>
39#include <pwd.h>
40#include <syslog.h>
41#include <errno(*__errno()).h>
42#include <rpc/rpc.h>
43#include <rpcsvc/rstat.h>
44
45extern void rstat_service(struct svc_req *, SVCXPRT *);
46
47void my_svc_run(void);
48
49int from_inetd = 1; /* started from inetd ? */
50int closedown = 20; /* how long to wait before going dormant */
51
52volatile sig_atomic_t gotsig;
53
54static void
55getsig(int signo)
56{
57 gotsig = 1;
58}
59
60
61int
62main(int argc, char *argv[])
63{
64 int sock = 0, proto = 0;
65 socklen_t fromlen;
66 struct passwd *pw;
67 struct sockaddr_storage from;
68 SVCXPRT *transp;
69
70 openlog("rpc.rstatd", LOG_NDELAY0x08|LOG_CONS0x02|LOG_PID0x01, LOG_DAEMON(3<<3));
71
72 if ((pw = getpwnam("_rstatd")) == NULL((void *)0)) {
73 syslog(LOG_ERR3, "no such user _rstatd");
74 exit(1);
75 }
76 if (chroot("/var/empty") == -1) {
77 syslog(LOG_ERR3, "cannot chdir to /var/empty.");
78 exit(1);
79 }
80 chdir("/");
81
82 setgroups(1, &pw->pw_gid);
83 setegid(pw->pw_gid);
The return value from the call to 'setegid' is not checked. If an error occurs in 'setegid', the following code may execute with unexpected privileges
84 setgid(pw->pw_gid);
85 seteuid(pw->pw_uid);
86 setuid(pw->pw_uid);
87
88 if (argc == 2)
89 closedown = strtonum(argv[1], 1, INT_MAX0x7fffffff, NULL((void *)0));
90 if (closedown == 0)
91 closedown = 20;
92
93 /*
94 * See if inetd started us
95 */
96 fromlen = sizeof(from);
97 if (getsockname(0, (struct sockaddr *)&from, &fromlen) == -1) {
98 from_inetd = 0;
99 sock = RPC_ANYSOCK-1;
100 proto = IPPROTO_UDP17;
101 }
102
103 if (!from_inetd) {
104 daemon(0, 0);
105
106 (void)pmap_unset(RSTATPROG((u_long)100001), RSTATVERS_TIME((u_long)3));
107 (void)pmap_unset(RSTATPROG((u_long)100001), RSTATVERS_SWTCH((u_long)2));
108 (void)pmap_unset(RSTATPROG((u_long)100001), RSTATVERS_ORIG((u_long)1));
109
110 (void) signal(SIGINT2, getsig);
111 (void) signal(SIGTERM15, getsig);
112 (void) signal(SIGHUP1, getsig);
113 }
114
115 transp = svcudp_create(sock);
116 if (transp == NULL((void *)0)) {
117 syslog(LOG_ERR3, "cannot create udp service.");
118 exit(1);
119 }
120 if (!svc_register(transp, RSTATPROG((u_long)100001), RSTATVERS_TIME((u_long)3), rstat_service, proto)) {
121 syslog(LOG_ERR3, "unable to register (RSTATPROG, RSTATVERS_TIME, udp).");
122 exit(1);
123 }
124 if (!svc_register(transp, RSTATPROG((u_long)100001), RSTATVERS_SWTCH((u_long)2), rstat_service, proto)) {
125 syslog(LOG_ERR3, "unable to register (RSTATPROG, RSTATVERS_SWTCH, udp).");
126 exit(1);
127 }
128 if (!svc_register(transp, RSTATPROG((u_long)100001), RSTATVERS_ORIG((u_long)1), rstat_service, proto)) {
129 syslog(LOG_ERR3, "unable to register (RSTATPROG, RSTATVERS_ORIG, udp).");
130 exit(1);
131 }
132
133 my_svc_run();
134 syslog(LOG_ERR3, "svc_run returned");
135 exit(1);
136}
137
138void
139my_svc_run(void)
140{
141 extern volatile sig_atomic_t wantupdatestat;
142 extern void updatestat(void);
143 struct pollfd *pfd = NULL((void *)0), *newp;
144 int nready, saved_max_pollfd = 0;
145
146 for (;;) {
147 if (wantupdatestat) {
148 wantupdatestat = 0;
149 updatestat();
150 }
151 if (gotsig) {
152 (void) pmap_unset(RSTATPROG((u_long)100001), RSTATVERS_TIME((u_long)3));
153 (void) pmap_unset(RSTATPROG((u_long)100001), RSTATVERS_SWTCH((u_long)2));
154 (void) pmap_unset(RSTATPROG((u_long)100001), RSTATVERS_ORIG((u_long)1));
155 exit(0);
156 }
157 if (svc_max_pollfd > saved_max_pollfd) {
158 newp = reallocarray(pfd, svc_max_pollfd, sizeof(*pfd));
159 if (newp == NULL((void *)0)) {
160 free(pfd);
161 perror("svc_run: - realloc failed");
162 return;
163 }
164 pfd = newp;
165 saved_max_pollfd = svc_max_pollfd;
166 }
167 memcpy(pfd, svc_pollfd, svc_max_pollfd * sizeof(*pfd));
168
169 nready = poll(pfd, svc_max_pollfd, INFTIM(-1));
170 switch (nready) {
171 case -1:
172 if (errno(*__errno()) == EINTR4)
173 continue;
174 perror("svc_run: - poll failed");
175 free(pfd);
176 return;
177 case 0:
178 continue;
179 default:
180 svc_getreq_poll(pfd, nready);
181 }
182 }
183}