Bug Summary

File:src/libexec/rpc.rstatd/rstatd.c
Warning:line 168, column 3
Null pointer passed as 1st argument to memory copy function

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)) {
1
Assuming the condition is false
2
Taking false branch
74 syslog(LOG_ERR3, "no such user _rstatd");
75 exit(1);
76 }
77 if (chroot("/var/empty") == -1) {
3
Assuming the condition is false
4
Taking false branch
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);
86 seteuid(pw->pw_uid);
87 setuid(pw->pw_uid);
88
89 if (argc == 2)
5
Assuming 'argc' is not equal to 2
6
Taking false branch
90 closedown = strtonum(argv[1], 1, INT_MAX2147483647, NULL((void *)0));
91 if (closedown
6.1
'closedown' is not equal to 0
== 0)
7
Taking false branch
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) {
8
Assuming the condition is false
9
Taking false branch
99 from_inetd = 0;
100 sock = RPC_ANYSOCK-1;
101 proto = IPPROTO_UDP17;
102 }
103
104 if (!from_inetd
9.1
'from_inetd' is 1
) {
10
Taking false branch
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)) {
11
Assuming 'transp' is not equal to NULL
12
Taking false branch
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)) {
13
Assuming the condition is false
14
Taking false branch
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)) {
15
Assuming the condition is false
16
Taking false branch
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)) {
17
Assuming the condition is false
18
Taking false branch
130 syslog(LOG_ERR3, "unable to register (RSTATPROG, RSTATVERS_ORIG, udp).");
131 exit(1);
132 }
133
134 my_svc_run();
19
Calling '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;
20
'pfd' initialized to a null pointer value
145 int nready, saved_max_pollfd = 0;
146
147 for (;;) {
21
Loop condition is true. Entering loop body
148 if (wantupdatestat) {
22
Assuming 'wantupdatestat' is 0
23
Taking false branch
149 wantupdatestat = 0;
150 updatestat();
151 }
152 if (gotsig) {
24
Assuming 'gotsig' is 0
25
Taking false branch
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) {
26
Assuming 'svc_max_pollfd' is <= 'saved_max_pollfd'
27
Taking false branch
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));
28
Null pointer passed as 1st argument to memory copy function
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}