Bug Summary

File:dev/usb/uhid.c
Warning:line 336, column 2
Value stored to 'error' is never read

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 uhid.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 static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -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 -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/dev/usb/uhid.c
1/* $OpenBSD: uhid.c,v 1.90 2023/04/20 10:49:57 brynet Exp $ */
2/* $NetBSD: uhid.c,v 1.57 2003/03/11 16:44:00 augustss Exp $ */
3
4/*
5 * Copyright (c) 1998 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Lennart Augustsson (lennart@augustsson.net) at
10 * Carlstedt Research & Technology.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34/*
35 * HID spec: https://www.usb.org/sites/default/files/hid1_11.pdf
36 */
37
38#include "fido.h"
39#include "ujoy.h"
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/kernel.h>
44#include <sys/malloc.h>
45#include <sys/signalvar.h>
46#include <sys/device.h>
47#include <sys/ioctl.h>
48#include <sys/conf.h>
49#include <sys/tty.h>
50#include <sys/selinfo.h>
51#include <sys/proc.h>
52#include <sys/vnode.h>
53
54#include <dev/usb/usb.h>
55#include <dev/usb/usbhid.h>
56
57#include <dev/usb/usbdevs.h>
58#include <dev/usb/usbdi.h>
59#include <dev/usb/usbdi_util.h>
60
61#include <dev/usb/uhidev.h>
62#include <dev/usb/uhid.h>
63
64#ifdef UHID_DEBUG
65#define DPRINTF(x) do { if (uhiddebug) printf x; } while (0)
66#define DPRINTFN(n,x) do { if (uhiddebug>(n)) printf x; } while (0)
67int uhiddebug = 0;
68#else
69#define DPRINTF(x)
70#define DPRINTFN(n,x)
71#endif
72
73int uhid_match(struct device *, void *, void *);
74
75struct cfdriver uhid_cd = {
76 NULL((void *)0), "uhid", DV_DULL
77};
78
79const struct cfattach uhid_ca = {
80 sizeof(struct uhid_softc),
81 uhid_match,
82 uhid_attach,
83 uhid_detach,
84};
85
86struct uhid_softc *
87uhid_lookup(dev_t dev)
88{
89 struct uhid_softc *sc = NULL((void *)0);
90 struct cdevsw *cdev;
91 struct cfdriver *cd;
92
93 cdev = &cdevsw[major(dev)(((unsigned)(dev) >> 8) & 0xff)];
94 if (cdev->d_open == uhidopen)
95 cd = &uhid_cd;
96#if NFIDO1 > 0
97 else if (cdev->d_open == fidoopen)
98 cd = &fido_cd;
99#endif
100#if NUJOY1 > 0
101 else if (cdev->d_open == ujoyopen)
102 cd = &ujoy_cd;
103#endif
104 else
105 return (NULL((void *)0));
106 if (UHIDUNIT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)))
< cd->cd_ndevs)
107 sc = cd->cd_devs[UHIDUNIT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)))
];
108
109 return (sc);
110}
111
112int
113uhid_match(struct device *parent, void *match, void *aux)
114{
115 struct uhidev_attach_arg *uha = aux;
116
117 if (UHIDEV_CLAIM_MULTIPLE_REPORTID(uha)((uha)->claimed != ((void *)0)))
118 return (UMATCH_NONE0);
119
120 return (UMATCH_IFACECLASS_GENERIC2);
121}
122
123void
124uhid_attach(struct device *parent, struct device *self, void *aux)
125{
126 struct uhid_softc *sc = (struct uhid_softc *)self;
127 struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
128 int size, repid;
129 void *desc;
130
131 sc->sc_hdev.sc_intr = uhid_intr;
132 sc->sc_hdev.sc_parent = uha->parent;
133 sc->sc_hdev.sc_udev = uha->uaa->device;
134 sc->sc_hdev.sc_report_id = uha->reportid;
135
136 uhidev_get_report_desc(uha->parent, &desc, &size);
137 repid = uha->reportid;
138 sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid);
139 sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid);
140 sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid);
141
142 printf(": input=%d, output=%d, feature=%d\n",
143 sc->sc_hdev.sc_isize, sc->sc_hdev.sc_osize, sc->sc_hdev.sc_fsize);
144}
145
146int
147uhid_detach(struct device *self, int flags)
148{
149 struct uhid_softc *sc = (struct uhid_softc *)self;
150 int s;
151 int maj, mn;
152
153 DPRINTF(("uhid_detach: sc=%p flags=%d\n", sc, flags));
154
155 if (sc->sc_hdev.sc_state & UHIDEV_OPEN0x01) {
156 s = splusb()splraise(0x2);
157 if (--sc->sc_refcnt >= 0) {
158 /* Wake everyone */
159 wakeup(&sc->sc_q);
160 /* Wait for processes to go away. */
161 usb_detach_wait(&sc->sc_hdev.sc_dev);
162 }
163 splx(s)spllower(s);
164 }
165
166 /* locate the major number */
167 for (maj = 0; maj < nchrdev; maj++)
168 if (cdevsw[maj].d_open == uhidopen)
169 break;
170
171 /* Nuke the vnodes for any open instances (calls close). */
172 mn = self->dv_unit;
173 vdevgone(maj, mn, mn, VCHR);
174
175 s = splusb()splraise(0x2);
176 klist_invalidate(&sc->sc_rsel.si_note);
177 splx(s)spllower(s);
178
179 return (0);
180}
181
182void
183uhid_intr(struct uhidev *addr, void *data, u_int len)
184{
185 struct uhid_softc *sc = (struct uhid_softc *)addr;
186
187#ifdef UHID_DEBUG
188 if (uhiddebug > 5) {
189 u_int32_t i;
190
191 DPRINTF(("uhid_intr: data ="));
192 for (i = 0; i < len; i++)
193 DPRINTF((" %02x", ((u_char *)data)[i]));
194 DPRINTF(("\n"));
195 }
196#endif
197
198 (void)b_to_q(data, len, &sc->sc_q);
199
200 if (sc->sc_state & UHID_ASLP0x01) {
201 sc->sc_state &= ~UHID_ASLP0x01;
202 DPRINTFN(5, ("uhid_intr: waking %p\n", &sc->sc_q));
203 wakeup(&sc->sc_q);
204 }
205 selwakeup(&sc->sc_rsel);
206}
207
208int
209uhidopen(dev_t dev, int flag, int mode, struct proc *p)
210{
211 return (uhid_do_open(dev, flag, mode, p));
212}
213
214int
215uhid_do_open(dev_t dev, int flag, int mode, struct proc *p)
216{
217 struct uhid_softc *sc;
218 int error;
219
220 if ((sc = uhid_lookup(dev)) == NULL((void *)0))
221 return (ENXIO6);
222
223 DPRINTF(("uhidopen: sc=%p\n", sc));
224
225 if (usbd_is_dying(sc->sc_hdev.sc_udev))
226 return (ENXIO6);
227
228 if (sc->sc_hdev.sc_state & UHIDEV_OPEN0x01)
229 return (EBUSY16);
230
231 clalloc(&sc->sc_q, UHID_BSIZE1020, 0);
232
233 error = uhidev_open(&sc->sc_hdev);
234 if (error) {
235 clfree(&sc->sc_q);
236 return (error);
237 }
238
239 sc->sc_obuf = malloc(sc->sc_hdev.sc_osize, M_USBDEV102, M_WAITOK0x0001);
240
241 return (0);
242}
243
244int
245uhidclose(dev_t dev, int flag, int mode, struct proc *p)
246{
247 struct uhid_softc *sc;
248
249 if ((sc = uhid_lookup(dev)) == NULL((void *)0))
250 return (ENXIO6);
251
252 DPRINTF(("uhidclose: sc=%p\n", sc));
253
254 clfree(&sc->sc_q);
255 free(sc->sc_obuf, M_USBDEV102, sc->sc_hdev.sc_osize);
256 uhidev_close(&sc->sc_hdev);
257
258 return (0);
259}
260
261int
262uhid_do_read(struct uhid_softc *sc, struct uio *uio, int flag)
263{
264 int s;
265 int error = 0;
266 size_t length;
267 u_char buffer[UHID_CHUNK128];
268
269 DPRINTFN(1, ("uhidread\n"));
270
271 s = splusb()splraise(0x2);
272 while (sc->sc_q.c_cc == 0) {
273 if (flag & IO_NDELAY0x10) {
274 splx(s)spllower(s);
275 return (EWOULDBLOCK35);
276 }
277 sc->sc_state |= UHID_ASLP0x01;
278 DPRINTFN(5, ("uhidread: sleep on %p\n", &sc->sc_q));
279 error = tsleep_nsec(&sc->sc_q, PZERO22|PCATCH0x100, "uhidrea", INFSLP0xffffffffffffffffULL);
280 DPRINTFN(5, ("uhidread: woke, error=%d\n", error));
281 if (usbd_is_dying(sc->sc_hdev.sc_udev))
282 error = EIO5;
283 if (error) {
284 sc->sc_state &= ~UHID_ASLP0x01;
285 break;
286 }
287 }
288 splx(s)spllower(s);
289
290 /* Transfer as many chunks as possible. */
291 while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0 && !error) {
292 length = ulmin(sc->sc_q.c_cc, uio->uio_resid);
293 if (length > sizeof(buffer))
294 length = sizeof(buffer);
295
296 /* Remove a small chunk from the input queue. */
297 (void) q_to_b(&sc->sc_q, buffer, length);
298 DPRINTFN(5, ("uhidread: got %zu chars\n", length));
299
300 /* Copy the data to the user process. */
301 if ((error = uiomove(buffer, length, uio)) != 0)
302 break;
303 }
304
305 return (error);
306}
307
308int
309uhidread(dev_t dev, struct uio *uio, int flag)
310{
311 struct uhid_softc *sc;
312 int error;
313
314 if ((sc = uhid_lookup(dev)) == NULL((void *)0))
315 return (ENXIO6);
316
317 sc->sc_refcnt++;
318 error = uhid_do_read(sc, uio, flag);
319 if (--sc->sc_refcnt < 0)
320 usb_detach_wakeup(&sc->sc_hdev.sc_dev);
321 return (error);
322}
323
324int
325uhid_do_write(struct uhid_softc *sc, struct uio *uio, int flag)
326{
327 int error;
328 int size;
329
330 DPRINTFN(1, ("uhidwrite\n"));
331
332 if (usbd_is_dying(sc->sc_hdev.sc_udev))
333 return (EIO5);
334
335 size = sc->sc_hdev.sc_osize;
336 error = 0;
Value stored to 'error' is never read
337 if (uio->uio_resid > size)
338 return (EMSGSIZE40);
339 else if (uio->uio_resid < size) {
340 /* don't leak kernel memory to the USB device */
341 memset(sc->sc_obuf + uio->uio_resid, 0, size - uio->uio_resid)__builtin_memset((sc->sc_obuf + uio->uio_resid), (0), (
size - uio->uio_resid))
;
342 }
343 error = uiomove(sc->sc_obuf, uio->uio_resid, uio);
344 if (!error) {
345 if (uhidev_set_report(sc->sc_hdev.sc_parent,
346 UHID_OUTPUT_REPORT0x02, sc->sc_hdev.sc_report_id, sc->sc_obuf,
347 size) != size)
348 error = EIO5;
349 }
350
351 return (error);
352}
353
354int
355uhidwrite(dev_t dev, struct uio *uio, int flag)
356{
357 struct uhid_softc *sc;
358 int error;
359
360 if ((sc = uhid_lookup(dev)) == NULL((void *)0))
361 return (ENXIO6);
362
363 sc->sc_refcnt++;
364 error = uhid_do_write(sc, uio, flag);
365 if (--sc->sc_refcnt < 0)
366 usb_detach_wakeup(&sc->sc_hdev.sc_dev);
367 return (error);
368}
369
370int
371uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, caddr_t addr,
372 int flag, struct proc *p)
373{
374 int rc;
375
376 DPRINTFN(2, ("uhidioctl: cmd=%lx\n", cmd));
377
378 if (usbd_is_dying(sc->sc_hdev.sc_udev))
379 return (EIO5);
380
381 switch (cmd) {
382 case FIONBIO((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((126)))
:
383 case FIOASYNC((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((125)))
:
384 /* All handled in the upper FS layer. */
385 break;
386
387 case USB_GET_DEVICEINFO((unsigned long)0x40000000 | ((sizeof(struct usb_device_info)
& 0x1fff) << 16) | ((('U')) << 8) | ((112)))
:
388 usbd_fill_deviceinfo(sc->sc_hdev.sc_udev,
389 (struct usb_device_info *)addr);
390 break;
391
392 case USB_GET_REPORT_DESC((unsigned long)0x40000000 | ((sizeof(struct usb_ctl_report_desc
) & 0x1fff) << 16) | ((('U')) << 8) | ((21)))
:
393 case USB_GET_REPORT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct usb_ctl_report) & 0x1fff) << 16) | ((('U'))
<< 8) | ((23)))
:
394 case USB_SET_REPORT((unsigned long)0x80000000 | ((sizeof(struct usb_ctl_report) &
0x1fff) << 16) | ((('U')) << 8) | ((24)))
:
395 case USB_GET_REPORT_ID((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('U')) << 8) | ((25)))
:
396 default:
397 rc = uhidev_ioctl(&sc->sc_hdev, cmd, addr, flag, p);
398 if (rc == -1)
399 rc = ENOTTY25;
400 return rc;
401 }
402 return (0);
403}
404
405int
406uhidioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
407{
408 struct uhid_softc *sc;
409 int error;
410
411 if ((sc = uhid_lookup(dev)) == NULL((void *)0))
412 return (ENXIO6);
413
414 sc->sc_refcnt++;
415 error = uhid_do_ioctl(sc, cmd, addr, flag, p);
416 if (--sc->sc_refcnt < 0)
417 usb_detach_wakeup(&sc->sc_hdev.sc_dev);
418 return (error);
419}
420
421void filt_uhidrdetach(struct knote *);
422int filt_uhidread(struct knote *, long);
423int uhidkqfilter(dev_t, struct knote *);
424
425void
426filt_uhidrdetach(struct knote *kn)
427{
428 struct uhid_softc *sc = (void *)kn->kn_hook;
429 int s;
430
431 s = splusb()splraise(0x2);
432 klist_remove_locked(&sc->sc_rsel.si_note, kn);
433 splx(s)spllower(s);
434}
435
436int
437filt_uhidread(struct knote *kn, long hint)
438{
439 struct uhid_softc *sc = (void *)kn->kn_hook;
440
441 kn->kn_datakn_kevent.data = sc->sc_q.c_cc;
442 return (kn->kn_datakn_kevent.data > 0);
443}
444
445const struct filterops uhidread_filtops = {
446 .f_flags = FILTEROP_ISFD0x00000001,
447 .f_attach = NULL((void *)0),
448 .f_detach = filt_uhidrdetach,
449 .f_event = filt_uhidread,
450};
451
452int
453uhidkqfilter(dev_t dev, struct knote *kn)
454{
455 struct uhid_softc *sc;
456 struct klist *klist;
457 int s;
458
459 if ((sc = uhid_lookup(dev)) == NULL((void *)0))
460 return (ENXIO6);
461
462 if (usbd_is_dying(sc->sc_hdev.sc_udev))
463 return (ENXIO6);
464
465 switch (kn->kn_filterkn_kevent.filter) {
466 case EVFILT_READ(-1):
467 klist = &sc->sc_rsel.si_note;
468 kn->kn_fop = &uhidread_filtops;
469 break;
470
471 case EVFILT_WRITE(-2):
472 return (seltrue_kqfilter(dev, kn));
473
474 default:
475 return (EINVAL22);
476 }
477
478 kn->kn_hook = (void *)sc;
479
480 s = splusb()splraise(0x2);
481 klist_insert_locked(klist, kn);
482 splx(s)spllower(s);
483
484 return (0);
485}