Bug Summary

File:src/usr.sbin/ldapd/control.c
Warning:line 238, column 7
Although the value stored to 'c' is used in the enclosing expression, the value is never actually read from 'c'

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 control.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/usr.sbin/ldapd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/ldapd -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/ldapd/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/usr.sbin/ldapd/control.c
1/* $OpenBSD: control.c,v 1.17 2021/04/20 21:11:56 dv Exp $ */
2
3/*
4 * Copyright (c) 2010 Martin Hedenfalk <martin@bzero.se>
5 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <sys/queue.h>
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <sys/socket.h>
24#include <sys/un.h>
25#include <sys/tree.h>
26
27#include <net/if.h>
28
29#include <errno(*__errno()).h>
30#include <event.h>
31#include <fcntl.h>
32#include <signal.h>
33#include <stdlib.h>
34#include <string.h>
35#include <unistd.h>
36
37#include "ldapd.h"
38#include "log.h"
39
40#define CONTROL_BACKLOG5 5
41
42struct ctl_connlist ctl_conns = TAILQ_HEAD_INITIALIZER(ctl_conns){ ((void*)0), &(ctl_conns).tqh_first };
43
44struct ctl_conn *control_connbyfd(int);
45void control_close(int, struct control_sock *);
46static void control_imsgev(struct imsgev *iev, int code, struct imsg *imsg);
47static void control_needfd(struct imsgev *iev);
48
49void
50control_init(struct control_sock *cs)
51{
52 struct sockaddr_un sun;
53 int fd;
54 mode_t old_umask, mode;
55
56 if (cs->cs_name == NULL((void*)0))
57 return;
58
59 if ((fd = socket(AF_UNIX1, SOCK_STREAM1 | SOCK_NONBLOCK0x4000, 0)) == -1)
60 fatal("control_init: socket");
61
62 memset(&sun, 0, sizeof(sun));
63 sun.sun_family = AF_UNIX1;
64 if (strlcpy(sun.sun_path, cs->cs_name,
65 sizeof(sun.sun_path)) >= sizeof(sun.sun_path))
66 fatalx("control_init: name too long");
67
68 if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == 0)
69 fatalx("control socket already listening");
70
71 if (unlink(cs->cs_name) == -1 && errno(*__errno()) != ENOENT2)
72 fatal("control_init: unlink");
73
74 if (cs->cs_restricted) {
75 old_umask = umask(S_IXUSR0000100|S_IXGRP0000010|S_IXOTH0000001);
76 mode = S_IRUSR0000400|S_IWUSR0000200|S_IRGRP0000040|S_IWGRP0000020|S_IROTH0000004|S_IWOTH0000002;
77 } else {
78 old_umask = umask(S_IXUSR0000100|S_IXGRP0000010|S_IWOTH0000002|S_IROTH0000004|S_IXOTH0000001);
79 mode = S_IRUSR0000400|S_IWUSR0000200|S_IRGRP0000040|S_IWGRP0000020;
80 }
81
82 if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
83 (void)umask(old_umask);
84 fatal("control_init: bind");
85 }
86 (void)umask(old_umask);
87
88 if (chmod(cs->cs_name, mode) == -1) {
89 (void)unlink(cs->cs_name);
90 fatal("control_init: chmod");
91 }
92
93 cs->cs_fd = fd;
94}
95
96void
97control_listen(struct control_sock *cs)
98{
99 if (cs->cs_name == NULL((void*)0))
100 return;
101
102 if (listen(cs->cs_fd, CONTROL_BACKLOG5) == -1)
103 fatal("control_listen: listen");
104
105 event_set(&cs->cs_ev, cs->cs_fd, EV_READ0x02,
106 control_accept, cs);
107 event_add(&cs->cs_ev, NULL((void*)0));
108 evtimer_set(&cs->cs_evt, control_accept, cs)event_set(&cs->cs_evt, -1, 0, control_accept, cs);
109}
110
111void
112control_cleanup(struct control_sock *cs)
113{
114 if (cs->cs_name == NULL((void*)0))
115 return;
116 event_del(&cs->cs_ev);
117 event_del(&cs->cs_evt);
118}
119
120/* ARGSUSED */
121void
122control_accept(int listenfd, short event, void *arg)
123{
124 struct control_sock *cs = arg;
125 int connfd;
126 socklen_t len;
127 struct sockaddr_un sun;
128 struct ctl_conn *c;
129
130 event_add(&cs->cs_ev, NULL((void*)0));
131 if ((event & EV_TIMEOUT0x01))
132 return;
133
134 len = sizeof(sun);
135 if ((connfd = accept_reserve(listenfd,
136 (struct sockaddr *)&sun, &len, FD_RESERVE8)) == -1) {
137 /*
138 * Pause accept if we are out of file descriptors, or
139 * libevent will haunt us here too.
140 */
141 if (errno(*__errno()) == ENFILE23 || errno(*__errno()) == EMFILE24) {
142 struct timeval evtpause = { 1, 0 };
143
144 event_del(&cs->cs_ev);
145 evtimer_add(&cs->cs_evt, &evtpause)event_add(&cs->cs_evt, &evtpause);
146 } else if (errno(*__errno()) != EWOULDBLOCK35 && errno(*__errno()) != EINTR4)
147 log_warn("control_accept");
148 return;
149 }
150
151 if ((c = calloc(1, sizeof(*c))) == NULL((void*)0)) {
152 log_warn("control_accept");
153 close(connfd);
154 return;
155 }
156
157 log_debug("accepted control fd %d", connfd);
158 TAILQ_INSERT_TAIL(&ctl_conns, c, entry)do { (c)->entry.tqe_next = ((void*)0); (c)->entry.tqe_prev
= (&ctl_conns)->tqh_last; *(&ctl_conns)->tqh_last
= (c); (&ctl_conns)->tqh_last = &(c)->entry.tqe_next
; } while (0)
;
159 imsgev_init(&c->iev, connfd, cs, control_imsgev, control_needfd);
160}
161
162struct ctl_conn *
163control_connbyfd(int fd)
164{
165 struct ctl_conn *c;
166
167 TAILQ_FOREACH(c, &ctl_conns, entry)for((c) = ((&ctl_conns)->tqh_first); (c) != ((void*)0)
; (c) = ((c)->entry.tqe_next))
{
168 if (c->iev.ibuf.fd == fd)
169 break;
170 }
171
172 return (c);
173}
174
175void
176control_close(int fd, struct control_sock *cs)
177{
178 struct ctl_conn *c;
179
180 if ((c = control_connbyfd(fd)) == NULL((void*)0)) {
181 log_warnx("control_close: fd %d: not found", fd);
182 return;
183 }
184
185 log_debug("close control fd %d", c->iev.ibuf.fd);
186 TAILQ_REMOVE(&ctl_conns, c, entry)do { if (((c)->entry.tqe_next) != ((void*)0)) (c)->entry
.tqe_next->entry.tqe_prev = (c)->entry.tqe_prev; else (
&ctl_conns)->tqh_last = (c)->entry.tqe_prev; *(c)->
entry.tqe_prev = (c)->entry.tqe_next; ; ; } while (0)
;
187 imsgev_clear(&c->iev);
188
189 /* Some file descriptors are available again. */
190 if (evtimer_pending(&cs->cs_evt, NULL)event_pending(&cs->cs_evt, 0x01, ((void*)0))) {
191 evtimer_del(&cs->cs_evt)event_del(&cs->cs_evt);
192 event_add(&cs->cs_ev, NULL((void*)0));
193 }
194
195 free(c);
196}
197
198static int
199send_stats(struct imsgev *iev)
200{
201 struct namespace *ns;
202 const struct btree_stat *st;
203 struct ns_stat nss;
204
205 imsgev_compose(iev, IMSG_CTL_STATS, 0, iev->ibuf.pid, -1,
206 &stats, sizeof(stats));
207
208 TAILQ_FOREACH(ns, &conf->namespaces, next)for((ns) = ((&conf->namespaces)->tqh_first); (ns) !=
((void*)0); (ns) = ((ns)->next.tqe_next))
{
209 if (namespace_has_referrals(ns))
210 continue;
211 memset(&nss, 0, sizeof(nss));
212 strlcpy(nss.suffix, ns->suffix, sizeof(nss.suffix));
213 if ((st = btree_stat(ns->data_db)) != NULL((void*)0))
214 bcopy(st, &nss.data_stat, sizeof(nss.data_stat));
215
216 if ((st = btree_stat(ns->indx_db)) != NULL((void*)0))
217 bcopy(st, &nss.indx_stat, sizeof(nss.indx_stat));
218
219 imsgev_compose(iev, IMSG_CTL_NSSTATS, 0, iev->ibuf.pid, -1,
220 &nss, sizeof(nss));
221 }
222
223 imsgev_compose(iev, IMSG_CTL_END, 0, iev->ibuf.pid, -1, NULL((void*)0), 0);
224
225 return 0;
226}
227
228static void
229control_imsgev(struct imsgev *iev, int code, struct imsg *imsg)
230{
231 struct control_sock *cs;
232 struct ctl_conn *c;
233 int fd, verbose;
234
235 cs = iev->data;
236 fd = iev->ibuf.fd;
237
238 if ((c = control_connbyfd(fd)) == NULL((void*)0)) {
Although the value stored to 'c' is used in the enclosing expression, the value is never actually read from 'c'
239 log_warnx("%s: fd %d: not found", __func__, fd);
240 return;
241 }
242
243 if (code != IMSGEV_IMSG0) {
244 control_close(fd, cs);
245 return;
246 }
247
248 log_debug("%s: got imsg %d on fd %d", __func__, imsg->hdr.type, fd);
249 switch (imsg->hdr.type) {
250 case IMSG_CTL_STATS:
251 if (send_stats(iev) == -1) {
252 log_debug("%s: failed to send statistics", __func__);
253 control_close(fd, cs);
254 }
255 break;
256 case IMSG_CTL_LOG_VERBOSE:
257 if (imsg->hdr.len != IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + sizeof(verbose))
258 break;
259
260 bcopy(imsg->data, &verbose, sizeof(verbose));
261 imsgev_compose(iev_ldapd, IMSG_CTL_LOG_VERBOSE, 0, 0, -1,
262 &verbose, sizeof(verbose));
263
264 log_setverbose(verbose);
265 break;
266 default:
267 log_warnx("%s: unexpected imsg %d", __func__, imsg->hdr.type);
268 break;
269 }
270}
271
272void
273control_needfd(struct imsgev *iev)
274{
275 fatal("should never need an fd for control messages");
276}
277
278int
279control_close_any(struct control_sock *cs)
280{
281 struct ctl_conn *c;
282
283 c = TAILQ_FIRST(&ctl_conns)((&ctl_conns)->tqh_first);
284 if (c != NULL((void*)0)) {
285 log_warn("closing oldest control connection");
286 control_close(c->iev.ibuf.fd, cs);
287 return (0);
288 }
289 log_warn("no control connections to close");
290 return (-1);
291}