Bug Summary

File:src/usr.sbin/ntpd/sensors.c
Warning:line 185, column 19
The left operand of '&' is a garbage value

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 sensors.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/ntpd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/ntpd -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/ntpd/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/ntpd/sensors.c
1/* $OpenBSD: sensors.c,v 1.54 2019/11/11 06:32:52 otto Exp $ */
2
3/*
4 * Copyright (c) 2006 Henning Brauer <henning@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20#include <sys/queue.h>
21#include <sys/time.h>
22#include <sys/sensors.h>
23#include <sys/sysctl.h>
24#include <sys/device.h>
25
26#include <errno(*__errno()).h>
27#include <fcntl.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <unistd.h>
32
33#include "ntpd.h"
34
35#define MAXDEVNAMLEN16 16
36
37int sensor_probe(int, char *, struct sensor *);
38void sensor_add(int, char *);
39void sensor_remove(struct ntp_sensor *);
40void sensor_update(struct ntp_sensor *);
41
42void
43sensor_init(void)
44{
45 TAILQ_INIT(&conf->ntp_sensors)do { (&conf->ntp_sensors)->tqh_first = ((void *)0);
(&conf->ntp_sensors)->tqh_last = &(&conf->
ntp_sensors)->tqh_first; } while (0)
;
46}
47
48int
49sensor_scan(void)
50{
51 int i, n, err;
52 char d[MAXDEVNAMLEN16];
53 struct sensor s;
54
55 n = 0;
56 for (i = 0; ; i++)
57 if ((err = sensor_probe(i, d, &s))) {
58 if (err == 0)
59 continue;
60 if (err == -1) /* no further sensors */
61 break;
62 sensor_add(i, d);
63 n++;
64 }
65
66 return n;
67}
68
69/*
70 * 1 = time sensor!
71 * 0 = sensor exists... but is not a time sensor
72 * -1: no sensor here, and no further sensors after this
73 */
74int
75sensor_probe(int devid, char *dxname, struct sensor *sensor)
76{
77 int mib[5];
78 size_t slen, sdlen;
79 struct sensordev sensordev;
80
81 mib[0] = CTL_HW6;
82 mib[1] = HW_SENSORS11;
83 mib[2] = devid;
84 mib[3] = SENSOR_TIMEDELTA;
85 mib[4] = 0;
86
87 sdlen = sizeof(sensordev);
88 if (sysctl(mib, 3, &sensordev, &sdlen, NULL((void *)0), 0) == -1) {
6
Assuming the condition is true
7
Taking true branch
89 if (errno(*__errno()) == ENXIO6)
8
Assuming the condition is false
9
Taking false branch
90 return (0);
91 if (errno(*__errno()) == ENOENT2)
10
Assuming the condition is true
11
Taking true branch
92 return (-1);
12
Returning without writing to 'sensor->flags'
13
Returning the value -1, which participates in a condition later
93 log_warn("sensor_probe sysctl");
94 }
95
96 if (sensordev.maxnumt[SENSOR_TIMEDELTA] == 0)
97 return (0);
98
99 strlcpy(dxname, sensordev.xname, MAXDEVNAMLEN16);
100
101 slen = sizeof(*sensor);
102 if (sysctl(mib, 5, sensor, &slen, NULL((void *)0), 0) == -1) {
103 if (errno(*__errno()) != ENOENT2)
104 log_warn("sensor_probe sysctl");
105 return (0);
106 }
107
108 return (1);
109}
110
111void
112sensor_add(int sensordev, char *dxname)
113{
114 struct ntp_sensor *s;
115 struct ntp_conf_sensor *cs;
116
117 /* check whether it is already there */
118 TAILQ_FOREACH(s, &conf->ntp_sensors, entry)for((s) = ((&conf->ntp_sensors)->tqh_first); (s) !=
((void *)0); (s) = ((s)->entry.tqe_next))
119 if (!strcmp(s->device, dxname))
120 return;
121
122 /* check whether it is requested in the config file */
123 for (cs = TAILQ_FIRST(&conf->ntp_conf_sensors)((&conf->ntp_conf_sensors)->tqh_first); cs != NULL((void *)0) &&
124 strcmp(cs->device, dxname) && strcmp(cs->device, "*");
125 cs = TAILQ_NEXT(cs, entry)((cs)->entry.tqe_next))
126 ; /* nothing */
127 if (cs == NULL((void *)0))
128 return;
129
130 if ((s = calloc(1, sizeof(*s))) == NULL((void *)0))
131 fatal("sensor_add calloc");
132
133 s->next = getmonotime();
134 s->weight = cs->weight;
135 s->correction = cs->correction;
136 s->stratum = cs->stratum - 1;
137 s->trusted = cs->trusted;
138 if ((s->device = strdup(dxname)) == NULL((void *)0))
139 fatal("sensor_add strdup");
140 s->sensordevid = sensordev;
141
142 if (cs->refstr == NULL((void *)0))
143 memcpy(&s->refid, SENSOR_DEFAULT_REFID"HARD", sizeof(s->refid));
144 else {
145 s->refid = 0;
146 strncpy((char *)&s->refid, cs->refstr, sizeof(s->refid));
147 }
148
149 TAILQ_INSERT_TAIL(&conf->ntp_sensors, s, entry)do { (s)->entry.tqe_next = ((void *)0); (s)->entry.tqe_prev
= (&conf->ntp_sensors)->tqh_last; *(&conf->
ntp_sensors)->tqh_last = (s); (&conf->ntp_sensors)->
tqh_last = &(s)->entry.tqe_next; } while (0)
;
150
151 log_debug("sensor %s added (weight %d, correction %.6f, refstr %.4u, "
152 "stratum %d)", s->device, s->weight, s->correction / 1e6,
153 s->refid, s->stratum);
154}
155
156void
157sensor_remove(struct ntp_sensor *s)
158{
159 TAILQ_REMOVE(&conf->ntp_sensors, s, entry)do { if (((s)->entry.tqe_next) != ((void *)0)) (s)->entry
.tqe_next->entry.tqe_prev = (s)->entry.tqe_prev; else (
&conf->ntp_sensors)->tqh_last = (s)->entry.tqe_prev
; *(s)->entry.tqe_prev = (s)->entry.tqe_next; ; ; } while
(0)
;
160 free(s->device);
161 free(s);
162}
163
164void
165sensor_query(struct ntp_sensor *s)
166{
167 char dxname[MAXDEVNAMLEN16];
168 struct sensor sensor;
169 double sens_time;
170
171 if (conf->settime)
1
Assuming field 'settime' is 0
2
Taking false branch
172 s->next = getmonotime() + SENSOR_QUERY_INTERVAL_SETTIME(15/3);
173 else
174 s->next = getmonotime() + SENSOR_QUERY_INTERVAL15;
175
176 /* rcvd is walltime here, monotime in client.c. not used elsewhere */
177 if (s->update.rcvd < time(NULL((void *)0)) - SENSOR_DATA_MAXAGE(15*60))
3
Assuming the condition is false
4
Taking false branch
178 s->update.good = 0;
179
180 if (!sensor_probe(s->sensordevid, dxname, &sensor)) {
5
Calling 'sensor_probe'
14
Returning from 'sensor_probe'
15
Taking false branch
181 sensor_remove(s);
182 return;
183 }
184
185 if (sensor.flags & SENSOR_FINVALID0x0001 ||
16
The left operand of '&' is a garbage value
186 sensor.status != SENSOR_S_OK)
187 return;
188
189 if (strcmp(dxname, s->device)) {
190 sensor_remove(s);
191 return;
192 }
193
194 if (sensor.tv.tv_sec == s->last) /* already seen */
195 return;
196
197 s->last = sensor.tv.tv_sec;
198
199 if (!s->trusted && !TAILQ_EMPTY(&conf->constraints)(((&conf->constraints)->tqh_first) == ((void *)0))) {
200 if (conf->constraint_median == 0) {
201 return;
202 }
203 sens_time = gettime() + (sensor.value / -1e9) +
204 (s->correction / 1e6);
205 if (constraint_check(sens_time) != 0) {
206 log_info("sensor %s: constraint check failed", s->device);
207 return;
208 }
209 }
210 /*
211 * TD = device time
212 * TS = system time
213 * sensor.value = TS - TD in ns
214 * if value is positive, system time is ahead
215 */
216 s->offsets[s->shift].offset = (sensor.value / -1e9) - getoffset() +
217 (s->correction / 1e6);
218 s->offsets[s->shift].rcvd = sensor.tv.tv_sec;
219 s->offsets[s->shift].good = 1;
220
221 s->offsets[s->shift].status.send_refid = s->refid;
222 /* stratum increased when sent out */
223 s->offsets[s->shift].status.stratum = s->stratum;
224 s->offsets[s->shift].status.rootdelay = 0;
225 s->offsets[s->shift].status.rootdispersion = 0;
226 s->offsets[s->shift].status.reftime = sensor.tv.tv_sec;
227 s->offsets[s->shift].status.synced = 1;
228
229 log_debug("sensor %s: offset %f", s->device,
230 s->offsets[s->shift].offset);
231
232 if (++s->shift >= SENSOR_OFFSETS6) {
233 s->shift = 0;
234 sensor_update(s);
235 }
236
237}
238
239void
240sensor_update(struct ntp_sensor *s)
241{
242 struct ntp_offset **offsets;
243 int i;
244
245 if ((offsets = calloc(SENSOR_OFFSETS6, sizeof(struct ntp_offset *))) ==
246 NULL((void *)0))
247 fatal("calloc sensor_update");
248
249 for (i = 0; i < SENSOR_OFFSETS6; i++)
250 offsets[i] = &s->offsets[i];
251
252 qsort(offsets, SENSOR_OFFSETS6, sizeof(struct ntp_offset *),
253 offset_compare);
254
255 i = SENSOR_OFFSETS6 / 2;
256 memcpy(&s->update, offsets[i], sizeof(s->update));
257 if (SENSOR_OFFSETS6 % 2 == 0) {
258 s->update.offset =
259 (offsets[i - 1]->offset + offsets[i]->offset) / 2;
260 }
261 free(offsets);
262
263 log_debug("sensor update %s: offset %f", s->device, s->update.offset);
264 priv_adjtime();
265}