Bug Summary

File:src/usr.sbin/ldapd/control.c
Warning:line 237, 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.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name control.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/usr.sbin/ldapd/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/usr.sbin/ldapd -internal-isystem /usr/local/llvm16/lib/clang/16/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 -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/usr.sbin/ldapd/control.c
1/* $OpenBSD: control.c,v 1.18 2023/03/08 04:43:13 guenther 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
120void
121control_accept(int listenfd, short event, void *arg)
122{
123 struct control_sock *cs = arg;
124 int connfd;
125 socklen_t len;
126 struct sockaddr_un sun;
127 struct ctl_conn *c;
128
129 event_add(&cs->cs_ev, NULL((void *)0));
130 if ((event & EV_TIMEOUT0x01))
131 return;
132
133 len = sizeof(sun);
134 if ((connfd = accept_reserve(listenfd,
135 (struct sockaddr *)&sun, &len, FD_RESERVE8)) == -1) {
136 /*
137 * Pause accept if we are out of file descriptors, or
138 * libevent will haunt us here too.
139 */
140 if (errno(*__errno()) == ENFILE23 || errno(*__errno()) == EMFILE24) {
141 struct timeval evtpause = { 1, 0 };
142
143 event_del(&cs->cs_ev);
144 evtimer_add(&cs->cs_evt, &evtpause)event_add(&cs->cs_evt, &evtpause);
145 } else if (errno(*__errno()) != EWOULDBLOCK35 && errno(*__errno()) != EINTR4)
146 log_warn("control_accept");
147 return;
148 }
149
150 if ((c = calloc(1, sizeof(*c))) == NULL((void *)0)) {
151 log_warn("control_accept");
152 close(connfd);
153 return;
154 }
155
156 log_debug("accepted control fd %d", connfd);
157 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)
;
158 imsgev_init(&c->iev, connfd, cs, control_imsgev, control_needfd);
159}
160
161struct ctl_conn *
162control_connbyfd(int fd)
163{
164 struct ctl_conn *c;
165
166 TAILQ_FOREACH(c, &ctl_conns, entry)for((c) = ((&ctl_conns)->tqh_first); (c) != ((void *)0
); (c) = ((c)->entry.tqe_next))
{
167 if (c->iev.ibuf.fd == fd)
168 break;
169 }
170
171 return (c);
172}
173
174void
175control_close(int fd, struct control_sock *cs)
176{
177 struct ctl_conn *c;
178
179 if ((c = control_connbyfd(fd)) == NULL((void *)0)) {
180 log_warnx("control_close: fd %d: not found", fd);
181 return;
182 }
183
184 log_debug("close control fd %d", c->iev.ibuf.fd);
185 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)
;
186 imsgev_clear(&c->iev);
187
188 /* Some file descriptors are available again. */
189 if (evtimer_pending(&cs->cs_evt, NULL)event_pending(&cs->cs_evt, 0x01, ((void *)0))) {
190 evtimer_del(&cs->cs_evt)event_del(&cs->cs_evt);
191 event_add(&cs->cs_ev, NULL((void *)0));
192 }
193
194 free(c);
195}
196
197static int
198send_stats(struct imsgev *iev)
199{
200 struct namespace *ns;
201 const struct btree_stat *st;
202 struct ns_stat nss;
203
204 imsgev_compose(iev, IMSG_CTL_STATS, 0, iev->ibuf.pid, -1,
205 &stats, sizeof(stats));
206
207 TAILQ_FOREACH(ns, &conf->namespaces, next)for((ns) = ((&conf->namespaces)->tqh_first); (ns) !=
((void *)0); (ns) = ((ns)->next.tqe_next))
{
208 if (namespace_has_referrals(ns))
209 continue;
210 memset(&nss, 0, sizeof(nss));
211 strlcpy(nss.suffix, ns->suffix, sizeof(nss.suffix));
212 if ((st = btree_stat(ns->data_db)) != NULL((void *)0))
213 bcopy(st, &nss.data_stat, sizeof(nss.data_stat));
214
215 if ((st = btree_stat(ns->indx_db)) != NULL((void *)0))
216 bcopy(st, &nss.indx_stat, sizeof(nss.indx_stat));
217
218 imsgev_compose(iev, IMSG_CTL_NSSTATS, 0, iev->ibuf.pid, -1,
219 &nss, sizeof(nss));
220 }
221
222 imsgev_compose(iev, IMSG_CTL_END, 0, iev->ibuf.pid, -1, NULL((void *)0), 0);
223
224 return 0;
225}
226
227static void
228control_imsgev(struct imsgev *iev, int code, struct imsg *imsg)
229{
230 struct control_sock *cs;
231 struct ctl_conn *c;
232 int fd, verbose;
233
234 cs = iev->data;
235 fd = iev->ibuf.fd;
236
237 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'
238 log_warnx("%s: fd %d: not found", __func__, fd);
239 return;
240 }
241
242 if (code != IMSGEV_IMSG0) {
243 control_close(fd, cs);
244 return;
245 }
246
247 log_debug("%s: got imsg %d on fd %d", __func__, imsg->hdr.type, fd);
248 switch (imsg->hdr.type) {
249 case IMSG_CTL_STATS:
250 if (send_stats(iev) == -1) {
251 log_debug("%s: failed to send statistics", __func__);
252 control_close(fd, cs);
253 }
254 break;
255 case IMSG_CTL_LOG_VERBOSE:
256 if (imsg->hdr.len != IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + sizeof(verbose))
257 break;
258
259 bcopy(imsg->data, &verbose, sizeof(verbose));
260 imsgev_compose(iev_ldapd, IMSG_CTL_LOG_VERBOSE, 0, 0, -1,
261 &verbose, sizeof(verbose));
262
263 log_setverbose(verbose);
264 break;
265 default:
266 log_warnx("%s: unexpected imsg %d", __func__, imsg->hdr.type);
267 break;
268 }
269}
270
271void
272control_needfd(struct imsgev *iev)
273{
274 fatal("should never need an fd for control messages");
275}
276
277int
278control_close_any(struct control_sock *cs)
279{
280 struct ctl_conn *c;
281
282 c = TAILQ_FIRST(&ctl_conns)((&ctl_conns)->tqh_first);
283 if (c != NULL((void *)0)) {
284 log_warn("closing oldest control connection");
285 control_close(c->iev.ibuf.fd, cs);
286 return (0);
287 }
288 log_warn("no control connections to close");
289 return (-1);
290}