Bug Summary

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