Bug Summary

File:miscfs/fuse/fuse_device.c
Warning:line 232, column 7
Although the value stored to 'fd' is used in the enclosing expression, the value is never actually read from 'fd'

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 fuse_device.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/miscfs/fuse/fuse_device.c
1/* $OpenBSD: fuse_device.c,v 1.40 2023/12/16 22:17:08 mvs Exp $ */
2/*
3 * Copyright (c) 2012-2013 Sylvestre Gallon <ccna.syl@gmail.com>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <sys/param.h>
19#include <sys/systm.h>
20#include <sys/fcntl.h>
21#include <sys/ioctl.h>
22#include <sys/event.h>
23#include <sys/malloc.h>
24#include <sys/mount.h>
25#include <sys/rwlock.h>
26#include <sys/stat.h>
27#include <sys/statvfs.h>
28#include <sys/vnode.h>
29#include <sys/fusebuf.h>
30
31#include "fusefs_node.h"
32#include "fusefs.h"
33
34#ifdef FUSE_DEBUG
35#define DPRINTF(fmt, arg...) printf("%s: " fmt, "fuse", ##arg)
36#else
37#define DPRINTF(fmt, arg...)
38#endif
39
40/*
41 * Locks used to protect struct members and global data
42 * l fd_lock
43 */
44
45SIMPLEQ_HEAD(fusebuf_head, fusebuf)struct fusebuf_head { struct fusebuf *sqh_first; struct fusebuf
**sqh_last; }
;
46
47struct fuse_d {
48 struct rwlock fd_lock;
49 struct fusefs_mnt *fd_fmp;
50 int fd_unit;
51
52 /*fusebufs queues*/
53 struct fusebuf_head fd_fbufs_in; /* [l] */
54 struct fusebuf_head fd_fbufs_wait;
55
56 /* kq fields */
57 struct klist fd_rklist; /* [l] */
58 LIST_ENTRY(fuse_d)struct { struct fuse_d *le_next; struct fuse_d **le_prev; } fd_list;
59};
60
61int stat_fbufs_in = 0;
62int stat_fbufs_wait = 0;
63int stat_opened_fusedev = 0;
64
65LIST_HEAD(, fuse_d)struct { struct fuse_d *lh_first; } fuse_d_list;
66struct fuse_d *fuse_lookup(int);
67
68void fuseattach(int);
69int fuseopen(dev_t, int, int, struct proc *);
70int fuseclose(dev_t, int, int, struct proc *);
71int fuseioctl(dev_t, u_long, caddr_t, int, struct proc *);
72int fuseread(dev_t, struct uio *, int);
73int fusewrite(dev_t, struct uio *, int);
74int fusekqfilter(dev_t dev, struct knote *kn);
75int filt_fuse_read(struct knote *, long);
76void filt_fuse_rdetach(struct knote *);
77int filt_fuse_modify(struct kevent *, struct knote *);
78int filt_fuse_process(struct knote *, struct kevent *);
79
80static const struct filterops fuse_rd_filtops = {
81 .f_flags = FILTEROP_ISFD0x00000001 | FILTEROP_MPSAFE0x00000002,
82 .f_attach = NULL((void *)0),
83 .f_detach = filt_fuse_rdetach,
84 .f_event = filt_fuse_read,
85 .f_modify = filt_fuse_modify,
86 .f_process = filt_fuse_process,
87};
88
89#ifdef FUSE_DEBUG
90static void
91fuse_dump_buff(char *buff, int len)
92{
93 char text[17];
94 int i;
95
96 if (len < 0) {
97 printf("invalid len: %d", len);
98 return;
99 }
100 if (buff == NULL((void *)0)) {
101 printf("invalid buff");
102 return;
103 }
104
105 memset(text, 0, 17)__builtin_memset((text), (0), (17));
106 for (i = 0; i < len; i++) {
107 if (i != 0 && (i % 16) == 0) {
108 printf(": %s\n", text);
109 memset(text, 0, 17)__builtin_memset((text), (0), (17));
110 }
111
112 printf("%.2x ", buff[i] & 0xff);
113
114 if (buff[i] > ' ' && buff[i] < '~')
115 text[i%16] = buff[i] & 0xff;
116 else
117 text[i%16] = '.';
118 }
119
120 if ((i % 16) != 0)
121 while ((i % 16) != 0) {
122 printf(" ");
123 i++;
124 }
125
126 printf(": %s\n", text);
127}
128#endif
129
130struct fuse_d *
131fuse_lookup(int unit)
132{
133 struct fuse_d *fd;
134
135 LIST_FOREACH(fd, &fuse_d_list, fd_list)for((fd) = ((&fuse_d_list)->lh_first); (fd)!= ((void *
)0); (fd) = ((fd)->fd_list.le_next))
136 if (fd->fd_unit == unit)
137 return (fd);
138 return (NULL((void *)0));
139}
140
141/*
142 * Cleanup all msgs from sc_fbufs_in and sc_fbufs_wait.
143 */
144void
145fuse_device_cleanup(dev_t dev)
146{
147 struct fuse_d *fd;
148 struct fusebuf *f, *ftmp, *lprev;
149
150 fd = fuse_lookup(minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
151 if (fd == NULL((void *)0))
152 return;
153
154 /* clear FIFO IN */
155 lprev = NULL((void *)0);
156 rw_enter_write(&fd->fd_lock);
157 SIMPLEQ_FOREACH_SAFE(f, &fd->fd_fbufs_in, fb_next, ftmp)for ((f) = ((&fd->fd_fbufs_in)->sqh_first); (f) &&
((ftmp) = ((f)->fb_hdr.fh_next.sqe_next), 1); (f) = (ftmp
))
{
158 DPRINTF("cleanup unprocessed msg in sc_fbufs_in\n");
159 if (lprev == NULL((void *)0))
160 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_in, fb_next)do { if (((&fd->fd_fbufs_in)->sqh_first = (&fd->
fd_fbufs_in)->sqh_first->fb_hdr.fh_next.sqe_next) == ((
void *)0)) (&fd->fd_fbufs_in)->sqh_last = &(&
fd->fd_fbufs_in)->sqh_first; } while (0)
;
161 else
162 SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_in, lprev,do { if (((lprev)->fb_hdr.fh_next.sqe_next = (lprev)->fb_hdr
.fh_next.sqe_next->fb_hdr.fh_next.sqe_next) == ((void *)0)
) (&fd->fd_fbufs_in)->sqh_last = &(lprev)->fb_hdr
.fh_next.sqe_next; } while (0)
163 fb_next)do { if (((lprev)->fb_hdr.fh_next.sqe_next = (lprev)->fb_hdr
.fh_next.sqe_next->fb_hdr.fh_next.sqe_next) == ((void *)0)
) (&fd->fd_fbufs_in)->sqh_last = &(lprev)->fb_hdr
.fh_next.sqe_next; } while (0)
;
164
165 stat_fbufs_in--;
166 f->fb_errfb_hdr.fh_err = ENXIO6;
167 wakeup(f);
168 lprev = f;
169 }
170 rw_exit_write(&fd->fd_lock);
171
172 /* clear FIFO WAIT*/
173 lprev = NULL((void *)0);
174 SIMPLEQ_FOREACH_SAFE(f, &fd->fd_fbufs_wait, fb_next, ftmp)for ((f) = ((&fd->fd_fbufs_wait)->sqh_first); (f) &&
((ftmp) = ((f)->fb_hdr.fh_next.sqe_next), 1); (f) = (ftmp
))
{
175 DPRINTF("umount unprocessed msg in sc_fbufs_wait\n");
176 if (lprev == NULL((void *)0))
177 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_wait, fb_next)do { if (((&fd->fd_fbufs_wait)->sqh_first = (&fd
->fd_fbufs_wait)->sqh_first->fb_hdr.fh_next.sqe_next
) == ((void *)0)) (&fd->fd_fbufs_wait)->sqh_last = &
(&fd->fd_fbufs_wait)->sqh_first; } while (0)
;
178 else
179 SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_wait, lprev,do { if (((lprev)->fb_hdr.fh_next.sqe_next = (lprev)->fb_hdr
.fh_next.sqe_next->fb_hdr.fh_next.sqe_next) == ((void *)0)
) (&fd->fd_fbufs_wait)->sqh_last = &(lprev)->
fb_hdr.fh_next.sqe_next; } while (0)
180 fb_next)do { if (((lprev)->fb_hdr.fh_next.sqe_next = (lprev)->fb_hdr
.fh_next.sqe_next->fb_hdr.fh_next.sqe_next) == ((void *)0)
) (&fd->fd_fbufs_wait)->sqh_last = &(lprev)->
fb_hdr.fh_next.sqe_next; } while (0)
;
181
182 stat_fbufs_wait--;
183 f->fb_errfb_hdr.fh_err = ENXIO6;
184 wakeup(f);
185 lprev = f;
186 }
187}
188
189void
190fuse_device_queue_fbuf(dev_t dev, struct fusebuf *fbuf)
191{
192 struct fuse_d *fd;
193
194 fd = fuse_lookup(minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
195 if (fd == NULL((void *)0))
196 return;
197
198 rw_enter_write(&fd->fd_lock);
199 SIMPLEQ_INSERT_TAIL(&fd->fd_fbufs_in, fbuf, fb_next)do { (fbuf)->fb_hdr.fh_next.sqe_next = ((void *)0); *(&
fd->fd_fbufs_in)->sqh_last = (fbuf); (&fd->fd_fbufs_in
)->sqh_last = &(fbuf)->fb_hdr.fh_next.sqe_next; } while
(0)
;
200 knote_locked(&fd->fd_rklist, 0);
201 rw_exit_write(&fd->fd_lock);
202 stat_fbufs_in++;
203}
204
205void
206fuse_device_set_fmp(struct fusefs_mnt *fmp, int set)
207{
208 struct fuse_d *fd;
209
210 fd = fuse_lookup(minor(fmp->dev)((unsigned)((fmp->dev) & 0xff) | (((fmp->dev) &
0xffff0000) >> 8))
);
211 if (fd == NULL((void *)0))
212 return;
213
214 fd->fd_fmp = set ? fmp : NULL((void *)0);
215}
216
217void
218fuseattach(int num)
219{
220 LIST_INIT(&fuse_d_list)do { ((&fuse_d_list)->lh_first) = ((void *)0); } while
(0)
;
221}
222
223int
224fuseopen(dev_t dev, int flags, int fmt, struct proc * p)
225{
226 struct fuse_d *fd;
227 int unit = minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
;
228
229 if (flags & O_EXCL0x0800)
230 return (EBUSY16); /* No exclusive opens */
231
232 if ((fd = fuse_lookup(unit)) != NULL((void *)0))
Although the value stored to 'fd' is used in the enclosing expression, the value is never actually read from 'fd'
233 return (EBUSY16);
234
235 fd = malloc(sizeof(*fd), M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008);
236 fd->fd_unit = unit;
237 SIMPLEQ_INIT(&fd->fd_fbufs_in)do { (&fd->fd_fbufs_in)->sqh_first = ((void *)0); (
&fd->fd_fbufs_in)->sqh_last = &(&fd->fd_fbufs_in
)->sqh_first; } while (0)
;
238 SIMPLEQ_INIT(&fd->fd_fbufs_wait)do { (&fd->fd_fbufs_wait)->sqh_first = ((void *)0);
(&fd->fd_fbufs_wait)->sqh_last = &(&fd->
fd_fbufs_wait)->sqh_first; } while (0)
;
239 rw_init(&fd->fd_lock, "fusedlk")_rw_init_flags(&fd->fd_lock, "fusedlk", 0, ((void *)0)
)
;
240 klist_init_rwlock(&fd->fd_rklist, &fd->fd_lock);
241
242 LIST_INSERT_HEAD(&fuse_d_list, fd, fd_list)do { if (((fd)->fd_list.le_next = (&fuse_d_list)->lh_first
) != ((void *)0)) (&fuse_d_list)->lh_first->fd_list
.le_prev = &(fd)->fd_list.le_next; (&fuse_d_list)->
lh_first = (fd); (fd)->fd_list.le_prev = &(&fuse_d_list
)->lh_first; } while (0)
;
243
244 stat_opened_fusedev++;
245 return (0);
246}
247
248int
249fuseclose(dev_t dev, int flags, int fmt, struct proc *p)
250{
251 struct fuse_d *fd;
252 int error;
253
254 fd = fuse_lookup(minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
255 if (fd == NULL((void *)0))
256 return (EINVAL22);
257
258 if (fd->fd_fmp) {
259 printf("fuse: device close without umount\n");
260 fd->fd_fmp->sess_init = 0;
261 fuse_device_cleanup(dev);
262 if ((vfs_busy(fd->fd_fmp->mp, VB_WRITE0x02 | VB_NOWAIT0x04)) != 0)
263 goto end;
264 error = dounmount(fd->fd_fmp->mp, MNT_FORCE0x00080000, p);
265 if (error)
266 printf("fuse: unmount failed with error %d\n", error);
267 fd->fd_fmp = NULL((void *)0);
268 }
269
270end:
271 LIST_REMOVE(fd, fd_list)do { if ((fd)->fd_list.le_next != ((void *)0)) (fd)->fd_list
.le_next->fd_list.le_prev = (fd)->fd_list.le_prev; *(fd
)->fd_list.le_prev = (fd)->fd_list.le_next; ((fd)->fd_list
.le_prev) = ((void *)-1); ((fd)->fd_list.le_next) = ((void
*)-1); } while (0)
;
272 free(fd, M_DEVBUF2, sizeof(*fd));
273 stat_opened_fusedev--;
274 return (0);
275}
276
277/*
278 * FIOCGETFBDAT Get fusebuf data from kernel to user
279 * FIOCSETFBDAT Set fusebuf data from user to kernel
280 */
281int
282fuseioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
283{
284 struct fb_ioctl_xch *ioexch;
285 struct fusebuf *lastfbuf;
286 struct fusebuf *fbuf;
287 struct fuse_d *fd;
288 int error = 0;
289
290 fd = fuse_lookup(minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
291 if (fd == NULL((void *)0))
292 return (ENXIO6);
293
294 switch (cmd) {
295 case FIOCGETFBDAT((unsigned long)0x80000000 | ((sizeof(struct fb_ioctl_xch) &
0x1fff) << 16) | ((('F')) << 8) | ((0)))
:
296 ioexch = (struct fb_ioctl_xch *)addr;
297
298 /* Looking for uuid in fd_fbufs_in */
299 rw_enter_write(&fd->fd_lock);
300 SIMPLEQ_FOREACH(fbuf, &fd->fd_fbufs_in, fb_next)for((fbuf) = ((&fd->fd_fbufs_in)->sqh_first); (fbuf
) != ((void *)0); (fbuf) = ((fbuf)->fb_hdr.fh_next.sqe_next
))
{
301 if (fbuf->fb_uuidfb_hdr.fh_uuid == ioexch->fbxch_uuid)
302 break;
303
304 lastfbuf = fbuf;
305 }
306 if (fbuf == NULL((void *)0)) {
307 rw_exit_write(&fd->fd_lock);
308 printf("fuse: Cannot find fusebuf\n");
309 return (EINVAL22);
310 }
311
312 /* Remove the fbuf from fd_fbufs_in */
313 if (fbuf == SIMPLEQ_FIRST(&fd->fd_fbufs_in)((&fd->fd_fbufs_in)->sqh_first))
314 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_in, fb_next)do { if (((&fd->fd_fbufs_in)->sqh_first = (&fd->
fd_fbufs_in)->sqh_first->fb_hdr.fh_next.sqe_next) == ((
void *)0)) (&fd->fd_fbufs_in)->sqh_last = &(&
fd->fd_fbufs_in)->sqh_first; } while (0)
;
315 else
316 SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_in, lastfbuf,do { if (((lastfbuf)->fb_hdr.fh_next.sqe_next = (lastfbuf)
->fb_hdr.fh_next.sqe_next->fb_hdr.fh_next.sqe_next) == (
(void *)0)) (&fd->fd_fbufs_in)->sqh_last = &(lastfbuf
)->fb_hdr.fh_next.sqe_next; } while (0)
317 fb_next)do { if (((lastfbuf)->fb_hdr.fh_next.sqe_next = (lastfbuf)
->fb_hdr.fh_next.sqe_next->fb_hdr.fh_next.sqe_next) == (
(void *)0)) (&fd->fd_fbufs_in)->sqh_last = &(lastfbuf
)->fb_hdr.fh_next.sqe_next; } while (0)
;
318 rw_exit_write(&fd->fd_lock);
319
320 stat_fbufs_in--;
321
322 /* Do not handle fbufs with bad len */
323 if (fbuf->fb_lenfb_hdr.fh_len != ioexch->fbxch_len) {
324 printf("fuse: Bad fusebuf len\n");
325 return (EINVAL22);
326 }
327
328 /* Update the userland fbuf */
329 error = copyout(fbuf->fb_dat, ioexch->fbxch_data,
330 ioexch->fbxch_len);
331 if (error) {
332 printf("fuse: cannot copyout\n");
333 return (error);
334 }
335
336#ifdef FUSE_DEBUG
337 fuse_dump_buff(fbuf->fb_dat, fbuf->fb_lenfb_hdr.fh_len);
338#endif
339
340 /* Adding fbuf in fd_fbufs_wait */
341 free(fbuf->fb_dat, M_FUSEFS65, fbuf->fb_lenfb_hdr.fh_len);
342 fbuf->fb_dat = NULL((void *)0);
343 SIMPLEQ_INSERT_TAIL(&fd->fd_fbufs_wait, fbuf, fb_next)do { (fbuf)->fb_hdr.fh_next.sqe_next = ((void *)0); *(&
fd->fd_fbufs_wait)->sqh_last = (fbuf); (&fd->fd_fbufs_wait
)->sqh_last = &(fbuf)->fb_hdr.fh_next.sqe_next; } while
(0)
;
344 stat_fbufs_wait++;
345 break;
346
347 case FIOCSETFBDAT((unsigned long)0x80000000 | ((sizeof(struct fb_ioctl_xch) &
0x1fff) << 16) | ((('F')) << 8) | ((1)))
:
348 DPRINTF("SET BUFFER\n");
349 ioexch = (struct fb_ioctl_xch *)addr;
350
351 /* looking for uuid in fd_fbufs_wait */
352 SIMPLEQ_FOREACH(fbuf, &fd->fd_fbufs_wait, fb_next)for((fbuf) = ((&fd->fd_fbufs_wait)->sqh_first); (fbuf
) != ((void *)0); (fbuf) = ((fbuf)->fb_hdr.fh_next.sqe_next
))
{
353 if (fbuf->fb_uuidfb_hdr.fh_uuid == ioexch->fbxch_uuid)
354 break;
355
356 lastfbuf = fbuf;
357 }
358 if (fbuf == NULL((void *)0)) {
359 printf("fuse: Cannot find fusebuf\n");
360 return (EINVAL22);
361 }
362
363 /* Do not handle fbufs with bad len */
364 if (fbuf->fb_lenfb_hdr.fh_len != ioexch->fbxch_len) {
365 printf("fuse: Bad fusebuf size\n");
366 return (EINVAL22);
367 }
368
369 /* fetching data from userland */
370 fbuf->fb_dat = malloc(ioexch->fbxch_len, M_FUSEFS65,
371 M_WAITOK0x0001 | M_ZERO0x0008);
372 error = copyin(ioexch->fbxch_data, fbuf->fb_dat,
373 ioexch->fbxch_len);
374 if (error) {
375 printf("fuse: Cannot copyin\n");
376 free(fbuf->fb_dat, M_FUSEFS65, fbuf->fb_lenfb_hdr.fh_len);
377 fbuf->fb_dat = NULL((void *)0);
378 return (error);
379 }
380
381#ifdef FUSE_DEBUG
382 fuse_dump_buff(fbuf->fb_dat, fbuf->fb_lenfb_hdr.fh_len);
383#endif
384
385 /* Remove fbuf from fd_fbufs_wait */
386 if (fbuf == SIMPLEQ_FIRST(&fd->fd_fbufs_wait)((&fd->fd_fbufs_wait)->sqh_first))
387 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_wait, fb_next)do { if (((&fd->fd_fbufs_wait)->sqh_first = (&fd
->fd_fbufs_wait)->sqh_first->fb_hdr.fh_next.sqe_next
) == ((void *)0)) (&fd->fd_fbufs_wait)->sqh_last = &
(&fd->fd_fbufs_wait)->sqh_first; } while (0)
;
388 else
389 SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_wait, lastfbuf,do { if (((lastfbuf)->fb_hdr.fh_next.sqe_next = (lastfbuf)
->fb_hdr.fh_next.sqe_next->fb_hdr.fh_next.sqe_next) == (
(void *)0)) (&fd->fd_fbufs_wait)->sqh_last = &(
lastfbuf)->fb_hdr.fh_next.sqe_next; } while (0)
390 fb_next)do { if (((lastfbuf)->fb_hdr.fh_next.sqe_next = (lastfbuf)
->fb_hdr.fh_next.sqe_next->fb_hdr.fh_next.sqe_next) == (
(void *)0)) (&fd->fd_fbufs_wait)->sqh_last = &(
lastfbuf)->fb_hdr.fh_next.sqe_next; } while (0)
;
391 stat_fbufs_wait--;
392 wakeup(fbuf);
393 break;
394 default:
395 error = EINVAL22;
396 }
397
398 return (error);
399}
400
401int
402fuseread(dev_t dev, struct uio *uio, int ioflag)
403{
404 struct fuse_d *fd;
405 struct fusebuf *fbuf;
406 struct fb_hdr hdr;
407 void *tmpaddr;
408 int error = 0;
409
410 /* We get the whole fusebuf or nothing */
411 if (uio->uio_resid != FUSEBUFSIZE(sizeof(struct fusebuf)))
412 return (EINVAL22);
413
414 fd = fuse_lookup(minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
415 if (fd == NULL((void *)0))
416 return (ENXIO6);
417
418 rw_enter_write(&fd->fd_lock);
419
420 if (SIMPLEQ_EMPTY(&fd->fd_fbufs_in)(((&fd->fd_fbufs_in)->sqh_first) == ((void *)0))) {
421 if (ioflag & O_NONBLOCK0x0004)
422 error = EAGAIN35;
423 goto end;
424 }
425 fbuf = SIMPLEQ_FIRST(&fd->fd_fbufs_in)((&fd->fd_fbufs_in)->sqh_first);
426
427 /* Do not send kernel pointers */
428 memcpy(&hdr.fh_next, &fbuf->fb_next, sizeof(fbuf->fb_next))__builtin_memcpy((&hdr.fh_next), (&fbuf->fb_hdr.fh_next
), (sizeof(fbuf->fb_hdr.fh_next)))
;
429 memset(&fbuf->fb_next, 0, sizeof(fbuf->fb_next))__builtin_memset((&fbuf->fb_hdr.fh_next), (0), (sizeof
(fbuf->fb_hdr.fh_next)))
;
430 tmpaddr = fbuf->fb_dat;
431 fbuf->fb_dat = NULL((void *)0);
432 error = uiomove(fbuf, FUSEBUFSIZE(sizeof(struct fusebuf)), uio);
433 if (error)
434 goto end;
435
436#ifdef FUSE_DEBUG
437 fuse_dump_buff((char *)fbuf, FUSEBUFSIZE(sizeof(struct fusebuf)));
438#endif
439 /* Restore kernel pointers */
440 memcpy(&fbuf->fb_next, &hdr.fh_next, sizeof(fbuf->fb_next))__builtin_memcpy((&fbuf->fb_hdr.fh_next), (&hdr.fh_next
), (sizeof(fbuf->fb_hdr.fh_next)))
;
441 fbuf->fb_dat = tmpaddr;
442
443 /* Remove the fbuf if it does not contains data */
444 if (fbuf->fb_lenfb_hdr.fh_len == 0) {
445 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_in, fb_next)do { if (((&fd->fd_fbufs_in)->sqh_first = (&fd->
fd_fbufs_in)->sqh_first->fb_hdr.fh_next.sqe_next) == ((
void *)0)) (&fd->fd_fbufs_in)->sqh_last = &(&
fd->fd_fbufs_in)->sqh_first; } while (0)
;
446 stat_fbufs_in--;
447 SIMPLEQ_INSERT_TAIL(&fd->fd_fbufs_wait, fbuf, fb_next)do { (fbuf)->fb_hdr.fh_next.sqe_next = ((void *)0); *(&
fd->fd_fbufs_wait)->sqh_last = (fbuf); (&fd->fd_fbufs_wait
)->sqh_last = &(fbuf)->fb_hdr.fh_next.sqe_next; } while
(0)
;
448 stat_fbufs_wait++;
449 }
450
451end:
452 rw_exit_write(&fd->fd_lock);
453 return (error);
454}
455
456int
457fusewrite(dev_t dev, struct uio *uio, int ioflag)
458{
459 struct fusebuf *lastfbuf;
460 struct fuse_d *fd;
461 struct fusebuf *fbuf;
462 struct fb_hdr hdr;
463 int error = 0;
464
465 fd = fuse_lookup(minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
466 if (fd == NULL((void *)0))
467 return (ENXIO6);
468
469 /* We get the whole fusebuf or nothing */
470 if (uio->uio_resid != FUSEBUFSIZE(sizeof(struct fusebuf)))
471 return (EINVAL22);
472
473 if ((error = uiomove(&hdr, sizeof(hdr), uio)) != 0)
474 return (error);
475
476 /* looking for uuid in fd_fbufs_wait */
477 SIMPLEQ_FOREACH(fbuf, &fd->fd_fbufs_wait, fb_next)for((fbuf) = ((&fd->fd_fbufs_wait)->sqh_first); (fbuf
) != ((void *)0); (fbuf) = ((fbuf)->fb_hdr.fh_next.sqe_next
))
{
478 if (fbuf->fb_uuidfb_hdr.fh_uuid == hdr.fh_uuid)
479 break;
480
481 lastfbuf = fbuf;
482 }
483 if (fbuf == NULL((void *)0))
484 return (EINVAL22);
485
486 /* Update fb_hdr */
487 fbuf->fb_lenfb_hdr.fh_len = hdr.fh_len;
488 fbuf->fb_errfb_hdr.fh_err = hdr.fh_err;
489 fbuf->fb_inofb_hdr.fh_ino = hdr.fh_ino;
490
491 /* Check for corrupted fbufs */
492 if ((fbuf->fb_lenfb_hdr.fh_len && fbuf->fb_errfb_hdr.fh_err) ||
493 SIMPLEQ_EMPTY(&fd->fd_fbufs_wait)(((&fd->fd_fbufs_wait)->sqh_first) == ((void *)0))) {
494 printf("fuse: dropping corrupted fusebuf\n");
495 error = EINVAL22;
496 goto end;
497 }
498
499 /* Get the missing data from the fbuf */
500 error = uiomove(&fbuf->FD, uio->uio_resid, uio);
501 if (error)
502 return error;
503 fbuf->fb_dat = NULL((void *)0);
504#ifdef FUSE_DEBUG
505 fuse_dump_buff((char *)fbuf, FUSEBUFSIZE(sizeof(struct fusebuf)));
506#endif
507
508 switch (fbuf->fb_typefb_hdr.fh_type) {
509 case FBT_INIT19:
510 fd->fd_fmp->sess_init = 1;
511 break ;
512 case FBT_DESTROY26:
513 fd->fd_fmp = NULL((void *)0);
514 break ;
515 }
516end:
517 /* Remove the fbuf if it does not contains data */
518 if (fbuf->fb_lenfb_hdr.fh_len == 0) {
519 if (fbuf == SIMPLEQ_FIRST(&fd->fd_fbufs_wait)((&fd->fd_fbufs_wait)->sqh_first))
520 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_wait, fb_next)do { if (((&fd->fd_fbufs_wait)->sqh_first = (&fd
->fd_fbufs_wait)->sqh_first->fb_hdr.fh_next.sqe_next
) == ((void *)0)) (&fd->fd_fbufs_wait)->sqh_last = &
(&fd->fd_fbufs_wait)->sqh_first; } while (0)
;
521 else
522 SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_wait, lastfbuf,do { if (((lastfbuf)->fb_hdr.fh_next.sqe_next = (lastfbuf)
->fb_hdr.fh_next.sqe_next->fb_hdr.fh_next.sqe_next) == (
(void *)0)) (&fd->fd_fbufs_wait)->sqh_last = &(
lastfbuf)->fb_hdr.fh_next.sqe_next; } while (0)
523 fb_next)do { if (((lastfbuf)->fb_hdr.fh_next.sqe_next = (lastfbuf)
->fb_hdr.fh_next.sqe_next->fb_hdr.fh_next.sqe_next) == (
(void *)0)) (&fd->fd_fbufs_wait)->sqh_last = &(
lastfbuf)->fb_hdr.fh_next.sqe_next; } while (0)
;
524 stat_fbufs_wait--;
525 if (fbuf->fb_typefb_hdr.fh_type == FBT_INIT19)
526 fb_delete(fbuf);
527 else
528 wakeup(fbuf);
529 }
530
531 return (error);
532}
533
534int
535fusekqfilter(dev_t dev, struct knote *kn)
536{
537 struct fuse_d *fd;
538 struct klist *klist;
539
540 fd = fuse_lookup(minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
541 if (fd == NULL((void *)0))
542 return (EINVAL22);
543
544 switch (kn->kn_filterkn_kevent.filter) {
545 case EVFILT_READ(-1):
546 klist = &fd->fd_rklist;
547 kn->kn_fop = &fuse_rd_filtops;
548 break;
549 case EVFILT_WRITE(-2):
550 return (seltrue_kqfilter(dev, kn));
551 default:
552 return (EINVAL22);
553 }
554
555 kn->kn_hook = fd;
556
557 klist_insert(klist, kn);
558
559 return (0);
560}
561
562void
563filt_fuse_rdetach(struct knote *kn)
564{
565 struct fuse_d *fd = kn->kn_hook;
566 struct klist *klist = &fd->fd_rklist;
567
568 klist_remove(klist, kn);
569}
570
571int
572filt_fuse_read(struct knote *kn, long hint)
573{
574 struct fuse_d *fd = kn->kn_hook;
575 int event = 0;
576
577 rw_assert_wrlock(&fd->fd_lock);
578
579 if (!SIMPLEQ_EMPTY(&fd->fd_fbufs_in)(((&fd->fd_fbufs_in)->sqh_first) == ((void *)0)))
580 event = 1;
581
582 return (event);
583}
584
585int
586filt_fuse_modify(struct kevent *kev, struct knote *kn)
587{
588 struct fuse_d *fd = kn->kn_hook;
589 int active;
590
591 rw_enter_write(&fd->fd_lock);
592 active = knote_modify(kev, kn);
593 rw_exit_write(&fd->fd_lock);
594
595 return (active);
596}
597
598int
599filt_fuse_process(struct knote *kn, struct kevent *kev)
600{
601 struct fuse_d *fd = kn->kn_hook;
602 int active;
603
604 rw_enter_write(&fd->fd_lock);
605 active = knote_process(kn, kev);
606 rw_exit_write(&fd->fd_lock);
607
608 return (active);
609}