Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name rstatd.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -fno-rounding-math -mconstructor-aliases -munwind-tables -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/lib/clang/13.0.0 -I /usr/src/libexec/rpc.rstatd/../../usr.bin/vmstat -D NOKVM -internal-isystem /usr/local/lib/clang/13.0.0/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 -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/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/libexec/rpc.rstatd/rstatd.c
1/* $OpenBSD: rstatd.c,v 1.30 2019/06/28 13:32:53 deraadt 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
54/* ARGSUSED */
55static void
56getsig(int signo)
57{
58 gotsig = 1;
59}
60
61
62int
63main(int argc, char *argv[])
64{
65 int sock = 0, proto = 0;
66 socklen_t fromlen;
67 struct passwd *pw;
68 struct sockaddr_storage from;
69 SVCXPRT *transp;
70
71 openlog("rpc.rstatd", LOG_NDELAY0x08|LOG_CONS0x02|LOG_PID0x01, LOG_DAEMON(3<<3));
72
73 if ((pw = getpwnam("_rstatd")) == NULL((void *)0)) {
74 syslog(LOG_ERR3, "no such user _rstatd");
75 exit(1);
76 }
77 if (chroot("/var/empty") == -1) {
78 syslog(LOG_ERR3, "cannot chdir to /var/empty.");
79 exit(1);
80 }
81 chdir("/");
82
83 setgroups(1, &pw->pw_gid);
84 setegid(pw->pw_gid);
85 setgid(pw->pw_gid);
The return value from the call to 'setgid' is not checked. If an error occurs in 'setgid', the following code may execute with unexpected privileges
86 seteuid(pw->pw_uid);
87 setuid(pw->pw_uid);
88
89 if (argc == 2)
90 closedown = strtonum(argv[1], 1, INT_MAX2147483647, NULL((void *)0));
91 if (closedown == 0)
92 closedown = 20;
93
94 /*
95 * See if inetd started us
96 */
97 fromlen = sizeof(from);
98 if (getsockname(0, (struct sockaddr *)&from, &fromlen) == -1) {
99 from_inetd = 0;
100 sock = RPC_ANYSOCK-1;
101 proto = IPPROTO_UDP17;
102 }
103
104 if (!from_inetd) {
105 daemon(0, 0);
106
107 (void)pmap_unset(RSTATPROG((u_long)100001), RSTATVERS_TIME((u_long)3));
108 (void)pmap_unset(RSTATPROG((u_long)100001), RSTATVERS_SWTCH((u_long)2));
109 (void)pmap_unset(RSTATPROG((u_long)100001), RSTATVERS_ORIG((u_long)1));
110
111 (void) signal(SIGINT2, getsig);
112 (void) signal(SIGTERM15, getsig);
113 (void) signal(SIGHUP1, getsig);
114 }
115
116 transp = svcudp_create(sock);
117 if (transp == NULL((void *)0)) {
118 syslog(LOG_ERR3, "cannot create udp service.");
119 exit(1);
120 }
121 if (!svc_register(transp, RSTATPROG((u_long)100001), RSTATVERS_TIME((u_long)3), rstat_service, proto)) {
122 syslog(LOG_ERR3, "unable to register (RSTATPROG, RSTATVERS_TIME, udp).");
123 exit(1);
124 }
125 if (!svc_register(transp, RSTATPROG((u_long)100001), RSTATVERS_SWTCH((u_long)2), rstat_service, proto)) {
126 syslog(LOG_ERR3, "unable to register (RSTATPROG, RSTATVERS_SWTCH, udp).");
127 exit(1);
128 }
129 if (!svc_register(transp, RSTATPROG((u_long)100001), RSTATVERS_ORIG((u_long)1), rstat_service, proto)) {
130 syslog(LOG_ERR3, "unable to register (RSTATPROG, RSTATVERS_ORIG, udp).");
131 exit(1);
132 }
133
134 my_svc_run();
135 syslog(LOG_ERR3, "svc_run returned");
136 exit(1);
137}
138
139void
140my_svc_run(void)
141{
142 extern volatile sig_atomic_t wantupdatestat;
143 extern void updatestat(void);
144 struct pollfd *pfd = NULL((void *)0), *newp;
145 int nready, saved_max_pollfd = 0;
146
147 for (;;) {
148 if (wantupdatestat) {
149 wantupdatestat = 0;
150 updatestat();
151 }
152 if (gotsig) {
153 (void) pmap_unset(RSTATPROG((u_long)100001), RSTATVERS_TIME((u_long)3));
154 (void) pmap_unset(RSTATPROG((u_long)100001), RSTATVERS_SWTCH((u_long)2));
155 (void) pmap_unset(RSTATPROG((u_long)100001), RSTATVERS_ORIG((u_long)1));
156 exit(0);
157 }
158 if (svc_max_pollfd > saved_max_pollfd) {
159 newp = reallocarray(pfd, svc_max_pollfd, sizeof(*pfd));
160 if (newp == NULL((void *)0)) {
161 free(pfd);
162 perror("svc_run: - realloc failed");
163 return;
164 }
165 pfd = newp;
166 saved_max_pollfd = svc_max_pollfd;
167 }
168 memcpy(pfd, svc_pollfd, svc_max_pollfd * sizeof(*pfd));
169
170 nready = poll(pfd, svc_max_pollfd, INFTIM(-1));
171 switch (nready) {
172 case -1:
173 if (errno(*__errno()) == EINTR4)
174 continue;
175 perror("svc_run: - poll failed");
176 free(pfd);
177 return;
178 case 0:
179 continue;
180 default:
181 svc_getreq_poll(pfd, nready);
182 }
183 }
184}