Bug Summary

File:kern/sys_generic.c
Warning:line 786, column 6
Value stored to 'error' is never read

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 sys_generic.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 static -mframe-pointer=all -relaxed-aliasing -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 -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/lib/clang/13.0.0 -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/swsmu -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/powerplay -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/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 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 -D CONFIG_DRM_AMD_DC_DCN3_0 -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 -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 /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/kern/sys_generic.c
1/* $OpenBSD: sys_generic.c,v 1.146 2021/12/11 09:28:26 visa Exp $ */
2/* $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $ */
3
4/*
5 * Copyright (c) 1996 Theo de Raadt
6 * Copyright (c) 1982, 1986, 1989, 1993
7 * The Regents of the University of California. All rights reserved.
8 * (c) UNIX System Laboratories, Inc.
9 * All or some portions of this file are derived from material licensed
10 * to the University of California by American Telephone and Telegraph
11 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
12 * the permission of UNIX System Laboratories, Inc.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)sys_generic.c 8.5 (Berkeley) 1/21/94
39 */
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/filedesc.h>
44#include <sys/ioctl.h>
45#include <sys/fcntl.h>
46#include <sys/vnode.h>
47#include <sys/file.h>
48#include <sys/proc.h>
49#include <sys/resourcevar.h>
50#include <sys/socketvar.h>
51#include <sys/signalvar.h>
52#include <sys/uio.h>
53#include <sys/kernel.h>
54#include <sys/stat.h>
55#include <sys/time.h>
56#include <sys/malloc.h>
57#include <sys/poll.h>
58#include <sys/eventvar.h>
59#ifdef KTRACE1
60#include <sys/ktrace.h>
61#endif
62#include <sys/sched.h>
63#include <sys/pledge.h>
64
65#include <sys/mount.h>
66#include <sys/syscallargs.h>
67
68#include <uvm/uvm_extern.h>
69
70/*
71 * Debug values:
72 * 1 - print implementation errors, things that should not happen.
73 * 2 - print ppoll(2) information, somewhat verbose
74 * 3 - print pselect(2) and ppoll(2) information, very verbose
75 */
76int kqpoll_debug = 0;
77#define DPRINTFN(v, x...)if (kqpoll_debug > v) { printf("%s(%d): ", ({struct cpu_info
*__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof
(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->
ps_comm, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0"
: "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self
))); __ci;})->ci_curproc->p_tid); printf(x...); }
if (kqpoll_debug > v) { \
78 printf("%s(%d): ", curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
->p_p->ps_comm, curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
->p_tid); \
79 printf(x); \
80}
81
82int pselregister(struct proc *, fd_set *[], fd_set *[], int, int *, int *);
83int pselcollect(struct proc *, struct kevent *, fd_set *[], int *);
84
85void pollscan(struct proc *, struct pollfd *, u_int, register_t *);
86int pollout(struct pollfd *, struct pollfd *, u_int);
87int dopselect(struct proc *, int, fd_set *, fd_set *, fd_set *,
88 struct timespec *, const sigset_t *, register_t *);
89int doppoll(struct proc *, struct pollfd *, u_int, struct timespec *,
90 const sigset_t *, register_t *);
91void doselwakeup(struct selinfo *);
92
93int
94iovec_copyin(const struct iovec *uiov, struct iovec **iovp, struct iovec *aiov,
95 unsigned int iovcnt, size_t *residp)
96{
97#ifdef KTRACE1
98 struct proc *p = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
;
99#endif
100 struct iovec *iov;
101 int error, i;
102 size_t resid = 0;
103
104 if (iovcnt > UIO_SMALLIOV8) {
105 if (iovcnt > IOV_MAX1024)
106 return (EINVAL22);
107 iov = mallocarray(iovcnt, sizeof(*iov), M_IOV19, M_WAITOK0x0001);
108 } else if (iovcnt > 0) {
109 iov = aiov;
110 } else {
111 return (EINVAL22);
112 }
113 *iovp = iov;
114
115 if ((error = copyin(uiov, iov, iovcnt * sizeof(*iov))))
116 return (error);
117
118#ifdef KTRACE1
119 if (KTRPOINT(p, KTR_STRUCT)((p)->p_p->ps_traceflag & (1<<(8)) &&
((p)->p_flag & 0x00000001) == 0)
)
120 ktriovec(p, iov, iovcnt)ktrstruct(p, "iovec", iov, (iovcnt) * sizeof(struct iovec));
121#endif
122
123 for (i = 0; i < iovcnt; i++) {
124 resid += iov->iov_len;
125 /*
126 * Writes return ssize_t because -1 is returned on error.
127 * Therefore we must restrict the length to SSIZE_MAX to
128 * avoid garbage return values. Note that the addition is
129 * guaranteed to not wrap because SSIZE_MAX * 2 < SIZE_MAX.
130 */
131 if (iov->iov_len > SSIZE_MAX0x7fffffffffffffffL || resid > SSIZE_MAX0x7fffffffffffffffL)
132 return (EINVAL22);
133 iov++;
134 }
135
136 if (residp != NULL((void *)0))
137 *residp = resid;
138
139 return (0);
140}
141
142void
143iovec_free(struct iovec *iov, unsigned int iovcnt)
144{
145 if (iovcnt > UIO_SMALLIOV8)
146 free(iov, M_IOV19, iovcnt * sizeof(*iov));
147}
148
149/*
150 * Read system call.
151 */
152int
153sys_read(struct proc *p, void *v, register_t *retval)
154{
155 struct sys_read_args /* {
156 syscallarg(int) fd;
157 syscallarg(void *) buf;
158 syscallarg(size_t) nbyte;
159 } */ *uap = v;
160 struct iovec iov;
161 struct uio auio;
162
163 iov.iov_base = SCARG(uap, buf)((uap)->buf.le.datum);
164 iov.iov_len = SCARG(uap, nbyte)((uap)->nbyte.le.datum);
165 if (iov.iov_len > SSIZE_MAX0x7fffffffffffffffL)
166 return (EINVAL22);
167
168 auio.uio_iov = &iov;
169 auio.uio_iovcnt = 1;
170 auio.uio_resid = iov.iov_len;
171
172 return (dofilereadv(p, SCARG(uap, fd)((uap)->fd.le.datum), &auio, 0, retval));
173}
174
175/*
176 * Scatter read system call.
177 */
178int
179sys_readv(struct proc *p, void *v, register_t *retval)
180{
181 struct sys_readv_args /* {
182 syscallarg(int) fd;
183 syscallarg(const struct iovec *) iovp;
184 syscallarg(int) iovcnt;
185 } */ *uap = v;
186 struct iovec aiov[UIO_SMALLIOV8], *iov = NULL((void *)0);
187 int error, iovcnt = SCARG(uap, iovcnt)((uap)->iovcnt.le.datum);
188 struct uio auio;
189 size_t resid;
190
191 error = iovec_copyin(SCARG(uap, iovp)((uap)->iovp.le.datum), &iov, aiov, iovcnt, &resid);
192 if (error)
193 goto done;
194
195 auio.uio_iov = iov;
196 auio.uio_iovcnt = iovcnt;
197 auio.uio_resid = resid;
198
199 error = dofilereadv(p, SCARG(uap, fd)((uap)->fd.le.datum), &auio, 0, retval);
200 done:
201 iovec_free(iov, iovcnt);
202 return (error);
203}
204
205int
206dofilereadv(struct proc *p, int fd, struct uio *uio, int flags,
207 register_t *retval)
208{
209 struct filedesc *fdp = p->p_fd;
210 struct file *fp;
211 long cnt, error = 0;
212 u_int iovlen;
213#ifdef KTRACE1
214 struct iovec *ktriov = NULL((void *)0);
215#endif
216
217 KASSERT(uio->uio_iov != NULL && uio->uio_iovcnt > 0)((uio->uio_iov != ((void *)0) && uio->uio_iovcnt
> 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/kern/sys_generic.c"
, 217, "uio->uio_iov != NULL && uio->uio_iovcnt > 0"
))
;
218 iovlen = uio->uio_iovcnt * sizeof(struct iovec);
219
220 if ((fp = fd_getfile_mode(fdp, fd, FREAD0x0001)) == NULL((void *)0))
221 return (EBADF9);
222
223 /* Checks for positioned read. */
224 if (flags & FO_POSITION0x00000001) {
225 struct vnode *vp = fp->f_data;
226
227 if (fp->f_type != DTYPE_VNODE1 || vp->v_type == VFIFO ||
228 (vp->v_flag & VISTTY0x0008)) {
229 error = ESPIPE29;
230 goto done;
231 }
232
233 if (uio->uio_offset < 0 && vp->v_type != VCHR) {
234 error = EINVAL22;
235 goto done;
236 }
237 }
238
239 uio->uio_rw = UIO_READ;
240 uio->uio_segflg = UIO_USERSPACE;
241 uio->uio_procp = p;
242#ifdef KTRACE1
243 /*
244 * if tracing, save a copy of iovec
245 */
246 if (KTRPOINT(p, KTR_GENIO)((p)->p_p->ps_traceflag & (1<<(4)) &&
((p)->p_flag & 0x00000001) == 0)
) {
247 ktriov = malloc(iovlen, M_TEMP127, M_WAITOK0x0001);
248 memcpy(ktriov, uio->uio_iov, iovlen)__builtin_memcpy((ktriov), (uio->uio_iov), (iovlen));
249 }
250#endif
251 cnt = uio->uio_resid;
252 error = (*fp->f_ops->fo_read)(fp, uio, flags);
253 if (error) {
254 if (uio->uio_resid != cnt && (error == ERESTART-1 ||
255 error == EINTR4 || error == EWOULDBLOCK35))
256 error = 0;
257 }
258 cnt -= uio->uio_resid;
259
260 mtx_enter(&fp->f_mtx);
261 fp->f_rxfer++;
262 fp->f_rbytes += cnt;
263 mtx_leave(&fp->f_mtx);
264#ifdef KTRACE1
265 if (ktriov != NULL((void *)0)) {
266 if (error == 0)
267 ktrgenio(p, fd, UIO_READ, ktriov, cnt);
268 free(ktriov, M_TEMP127, iovlen);
269 }
270#endif
271 *retval = cnt;
272 done:
273 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
274 return (error);
275}
276
277/*
278 * Write system call
279 */
280int
281sys_write(struct proc *p, void *v, register_t *retval)
282{
283 struct sys_write_args /* {
284 syscallarg(int) fd;
285 syscallarg(const void *) buf;
286 syscallarg(size_t) nbyte;
287 } */ *uap = v;
288 struct iovec iov;
289 struct uio auio;
290
291 iov.iov_base = (void *)SCARG(uap, buf)((uap)->buf.le.datum);
292 iov.iov_len = SCARG(uap, nbyte)((uap)->nbyte.le.datum);
293 if (iov.iov_len > SSIZE_MAX0x7fffffffffffffffL)
294 return (EINVAL22);
295
296 auio.uio_iov = &iov;
297 auio.uio_iovcnt = 1;
298 auio.uio_resid = iov.iov_len;
299
300 return (dofilewritev(p, SCARG(uap, fd)((uap)->fd.le.datum), &auio, 0, retval));
301}
302
303/*
304 * Gather write system call
305 */
306int
307sys_writev(struct proc *p, void *v, register_t *retval)
308{
309 struct sys_writev_args /* {
310 syscallarg(int) fd;
311 syscallarg(const struct iovec *) iovp;
312 syscallarg(int) iovcnt;
313 } */ *uap = v;
314 struct iovec aiov[UIO_SMALLIOV8], *iov = NULL((void *)0);
315 int error, iovcnt = SCARG(uap, iovcnt)((uap)->iovcnt.le.datum);
316 struct uio auio;
317 size_t resid;
318
319 error = iovec_copyin(SCARG(uap, iovp)((uap)->iovp.le.datum), &iov, aiov, iovcnt, &resid);
320 if (error)
321 goto done;
322
323 auio.uio_iov = iov;
324 auio.uio_iovcnt = iovcnt;
325 auio.uio_resid = resid;
326
327 error = dofilewritev(p, SCARG(uap, fd)((uap)->fd.le.datum), &auio, 0, retval);
328 done:
329 iovec_free(iov, iovcnt);
330 return (error);
331}
332
333int
334dofilewritev(struct proc *p, int fd, struct uio *uio, int flags,
335 register_t *retval)
336{
337 struct filedesc *fdp = p->p_fd;
338 struct file *fp;
339 long cnt, error = 0;
340 u_int iovlen;
341#ifdef KTRACE1
342 struct iovec *ktriov = NULL((void *)0);
343#endif
344
345 KASSERT(uio->uio_iov != NULL && uio->uio_iovcnt > 0)((uio->uio_iov != ((void *)0) && uio->uio_iovcnt
> 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/kern/sys_generic.c"
, 345, "uio->uio_iov != NULL && uio->uio_iovcnt > 0"
))
;
346 iovlen = uio->uio_iovcnt * sizeof(struct iovec);
347
348 if ((fp = fd_getfile_mode(fdp, fd, FWRITE0x0002)) == NULL((void *)0))
349 return (EBADF9);
350
351 /* Checks for positioned write. */
352 if (flags & FO_POSITION0x00000001) {
353 struct vnode *vp = fp->f_data;
354
355 if (fp->f_type != DTYPE_VNODE1 || vp->v_type == VFIFO ||
356 (vp->v_flag & VISTTY0x0008)) {
357 error = ESPIPE29;
358 goto done;
359 }
360
361 if (uio->uio_offset < 0 && vp->v_type != VCHR) {
362 error = EINVAL22;
363 goto done;
364 }
365 }
366
367 uio->uio_rw = UIO_WRITE;
368 uio->uio_segflg = UIO_USERSPACE;
369 uio->uio_procp = p;
370#ifdef KTRACE1
371 /*
372 * if tracing, save a copy of iovec
373 */
374 if (KTRPOINT(p, KTR_GENIO)((p)->p_p->ps_traceflag & (1<<(4)) &&
((p)->p_flag & 0x00000001) == 0)
) {
375 ktriov = malloc(iovlen, M_TEMP127, M_WAITOK0x0001);
376 memcpy(ktriov, uio->uio_iov, iovlen)__builtin_memcpy((ktriov), (uio->uio_iov), (iovlen));
377 }
378#endif
379 cnt = uio->uio_resid;
380 error = (*fp->f_ops->fo_write)(fp, uio, flags);
381 if (error) {
382 if (uio->uio_resid != cnt && (error == ERESTART-1 ||
383 error == EINTR4 || error == EWOULDBLOCK35))
384 error = 0;
385 if (error == EPIPE32) {
386 KERNEL_LOCK()_kernel_lock();
387 ptsignal(p, SIGPIPE13, STHREAD);
388 KERNEL_UNLOCK()_kernel_unlock();
389 }
390 }
391 cnt -= uio->uio_resid;
392
393 mtx_enter(&fp->f_mtx);
394 fp->f_wxfer++;
395 fp->f_wbytes += cnt;
396 mtx_leave(&fp->f_mtx);
397#ifdef KTRACE1
398 if (ktriov != NULL((void *)0)) {
399 if (error == 0)
400 ktrgenio(p, fd, UIO_WRITE, ktriov, cnt);
401 free(ktriov, M_TEMP127, iovlen);
402 }
403#endif
404 *retval = cnt;
405 done:
406 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
407 return (error);
408}
409
410/*
411 * Ioctl system call
412 */
413int
414sys_ioctl(struct proc *p, void *v, register_t *retval)
415{
416 struct sys_ioctl_args /* {
417 syscallarg(int) fd;
418 syscallarg(u_long) com;
419 syscallarg(void *) data;
420 } */ *uap = v;
421 struct file *fp;
422 struct filedesc *fdp = p->p_fd;
423 u_long com = SCARG(uap, com)((uap)->com.le.datum);
424 int error = 0;
425 u_int size = 0;
426 caddr_t data, memp = NULL((void *)0);
427 int tmp;
428#define STK_PARAMS128 128
429 long long stkbuf[STK_PARAMS128 / sizeof(long long)];
430
431 if ((fp = fd_getfile_mode(fdp, SCARG(uap, fd)((uap)->fd.le.datum), FREAD0x0001|FWRITE0x0002)) == NULL((void *)0))
432 return (EBADF9);
433
434 if (fp->f_type == DTYPE_SOCKET2) {
435 struct socket *so = fp->f_data;
436
437 if (so->so_state & SS_DNS0x4000) {
438 error = EINVAL22;
439 goto out;
440 }
441 }
442
443 error = pledge_ioctl(p, com, fp);
444 if (error)
445 goto out;
446
447 switch (com) {
448 case FIONCLEX((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('f')) << 8) | ((2)))
:
449 case FIOCLEX((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('f')) << 8) | ((1)))
:
450 fdplock(fdp)do { do { int _s = rw_status(&netlock); if ((splassert_ctl
> 0) && (_s == 0x0001UL)) splassert_fail(0, 0x0001UL
, __func__); } while (0); rw_enter_write(&(fdp)->fd_lock
); } while (0)
;
451 if (com == FIONCLEX((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('f')) << 8) | ((2)))
)
452 fdp->fd_ofileflags[SCARG(uap, fd)((uap)->fd.le.datum)] &= ~UF_EXCLOSE0x01;
453 else
454 fdp->fd_ofileflags[SCARG(uap, fd)((uap)->fd.le.datum)] |= UF_EXCLOSE0x01;
455 fdpunlock(fdp)rw_exit_write(&(fdp)->fd_lock);
456 goto out;
457 }
458
459 /*
460 * Interpret high order word to find amount of data to be
461 * copied to/from the user's address space.
462 */
463 size = IOCPARM_LEN(com)(((com) >> 16) & 0x1fff);
464 if (size > IOCPARM_MAX(1 << 12)) {
465 error = ENOTTY25;
466 goto out;
467 }
468 if (size > sizeof (stkbuf)) {
469 memp = malloc(size, M_IOCTLOPS14, M_WAITOK0x0001);
470 data = memp;
471 } else
472 data = (caddr_t)stkbuf;
473 if (com&IOC_IN(unsigned long)0x80000000) {
474 if (size) {
475 error = copyin(SCARG(uap, data)((uap)->data.le.datum), data, size);
476 if (error) {
477 goto out;
478 }
479 } else
480 *(caddr_t *)data = SCARG(uap, data)((uap)->data.le.datum);
481 } else if ((com&IOC_OUT(unsigned long)0x40000000) && size)
482 /*
483 * Zero the buffer so the user always
484 * gets back something deterministic.
485 */
486 memset(data, 0, size)__builtin_memset((data), (0), (size));
487 else if (com&IOC_VOID(unsigned long)0x20000000)
488 *(caddr_t *)data = SCARG(uap, data)((uap)->data.le.datum);
489
490 switch (com) {
491
492 case FIONBIO((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((126)))
:
493 if ((tmp = *(int *)data) != 0)
494 atomic_setbits_intx86_atomic_setbits_u32(&fp->f_flag, FNONBLOCK0x0004);
495 else
496 atomic_clearbits_intx86_atomic_clearbits_u32(&fp->f_flag, FNONBLOCK0x0004);
497 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((126)))
, (caddr_t)&tmp, p);
498 break;
499
500 case FIOASYNC((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((125)))
:
501 if ((tmp = *(int *)data) != 0)
502 atomic_setbits_intx86_atomic_setbits_u32(&fp->f_flag, FASYNC0x0040);
503 else
504 atomic_clearbits_intx86_atomic_clearbits_u32(&fp->f_flag, FASYNC0x0040);
505 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((125)))
, (caddr_t)&tmp, p);
506 break;
507
508 default:
509 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
510 break;
511 }
512 /*
513 * Copy any data to user, size was
514 * already set and checked above.
515 */
516 if (error == 0 && (com&IOC_OUT(unsigned long)0x40000000) && size)
517 error = copyout(data, SCARG(uap, data)((uap)->data.le.datum), size);
518out:
519 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
520 free(memp, M_IOCTLOPS14, size);
521 return (error);
522}
523
524int selwait, nselcoll;
525
526/*
527 * Select system call.
528 */
529int
530sys_select(struct proc *p, void *v, register_t *retval)
531{
532 struct sys_select_args /* {
533 syscallarg(int) nd;
534 syscallarg(fd_set *) in;
535 syscallarg(fd_set *) ou;
536 syscallarg(fd_set *) ex;
537 syscallarg(struct timeval *) tv;
538 } */ *uap = v;
539
540 struct timespec ts, *tsp = NULL((void *)0);
541 int error;
542
543 if (SCARG(uap, tv)((uap)->tv.le.datum) != NULL((void *)0)) {
544 struct timeval tv;
545 if ((error = copyin(SCARG(uap, tv)((uap)->tv.le.datum), &tv, sizeof tv)) != 0)
546 return (error);
547#ifdef KTRACE1
548 if (KTRPOINT(p, KTR_STRUCT)((p)->p_p->ps_traceflag & (1<<(8)) &&
((p)->p_flag & 0x00000001) == 0)
)
549 ktrreltimeval(p, &tv)ktrstruct((p), "reltimeval", (&tv), sizeof(struct timeval
))
;
550#endif
551 if (tv.tv_sec < 0 || !timerisvalid(&tv)((&tv)->tv_usec >= 0 && (&tv)->tv_usec
< 1000000)
)
552 return (EINVAL22);
553 TIMEVAL_TO_TIMESPEC(&tv, &ts)do { (&ts)->tv_sec = (&tv)->tv_sec; (&ts)->
tv_nsec = (&tv)->tv_usec * 1000; } while (0)
;
554 tsp = &ts;
555 }
556
557 return (dopselect(p, SCARG(uap, nd)((uap)->nd.le.datum), SCARG(uap, in)((uap)->in.le.datum), SCARG(uap, ou)((uap)->ou.le.datum),
558 SCARG(uap, ex)((uap)->ex.le.datum), tsp, NULL((void *)0), retval));
559}
560
561int
562sys_pselect(struct proc *p, void *v, register_t *retval)
563{
564 struct sys_pselect_args /* {
565 syscallarg(int) nd;
566 syscallarg(fd_set *) in;
567 syscallarg(fd_set *) ou;
568 syscallarg(fd_set *) ex;
569 syscallarg(const struct timespec *) ts;
570 syscallarg(const sigset_t *) mask;
571 } */ *uap = v;
572
573 struct timespec ts, *tsp = NULL((void *)0);
574 sigset_t ss, *ssp = NULL((void *)0);
575 int error;
576
577 if (SCARG(uap, ts)((uap)->ts.le.datum) != NULL((void *)0)) {
578 if ((error = copyin(SCARG(uap, ts)((uap)->ts.le.datum), &ts, sizeof ts)) != 0)
579 return (error);
580#ifdef KTRACE1
581 if (KTRPOINT(p, KTR_STRUCT)((p)->p_p->ps_traceflag & (1<<(8)) &&
((p)->p_flag & 0x00000001) == 0)
)
582 ktrreltimespec(p, &ts)ktrstruct((p), "reltimespec", (&ts), sizeof(struct timespec
))
;
583#endif
584 if (ts.tv_sec < 0 || !timespecisvalid(&ts)((&ts)->tv_nsec >= 0 && (&ts)->tv_nsec
< 1000000000L)
)
585 return (EINVAL22);
586 tsp = &ts;
587 }
588 if (SCARG(uap, mask)((uap)->mask.le.datum) != NULL((void *)0)) {
589 if ((error = copyin(SCARG(uap, mask)((uap)->mask.le.datum), &ss, sizeof ss)) != 0)
590 return (error);
591 ssp = &ss;
592 }
593
594 return (dopselect(p, SCARG(uap, nd)((uap)->nd.le.datum), SCARG(uap, in)((uap)->in.le.datum), SCARG(uap, ou)((uap)->ou.le.datum),
595 SCARG(uap, ex)((uap)->ex.le.datum), tsp, ssp, retval));
596}
597
598int
599dopselect(struct proc *p, int nd, fd_set *in, fd_set *ou, fd_set *ex,
600 struct timespec *timeout, const sigset_t *sigmask, register_t *retval)
601{
602 struct kqueue_scan_state scan;
603 struct timespec zerots = {};
604 fd_mask__fd_mask bits[6];
605 fd_set *pibits[3], *pobits[3];
606 int error, ncollected = 0, nevents = 0;
607 u_int ni;
608
609 if (nd < 0)
610 return (EINVAL22);
611 if (nd > p->p_fd->fd_nfiles) {
612 /* forgiving; slightly wrong */
613 nd = p->p_fd->fd_nfiles;
614 }
615 ni = howmany(nd, NFDBITS)(((nd) + ((((unsigned)(sizeof(__fd_mask) * 8))) - 1)) / (((unsigned
)(sizeof(__fd_mask) * 8))))
* sizeof(fd_mask__fd_mask);
616 if (ni > sizeof(bits[0])) {
617 caddr_t mbits;
618
619 mbits = mallocarray(6, ni, M_TEMP127, M_WAITOK0x0001|M_ZERO0x0008);
620 pibits[0] = (fd_set *)&mbits[ni * 0];
621 pibits[1] = (fd_set *)&mbits[ni * 1];
622 pibits[2] = (fd_set *)&mbits[ni * 2];
623 pobits[0] = (fd_set *)&mbits[ni * 3];
624 pobits[1] = (fd_set *)&mbits[ni * 4];
625 pobits[2] = (fd_set *)&mbits[ni * 5];
626 } else {
627 memset(bits, 0, sizeof(bits))__builtin_memset((bits), (0), (sizeof(bits)));
628 pibits[0] = (fd_set *)&bits[0];
629 pibits[1] = (fd_set *)&bits[1];
630 pibits[2] = (fd_set *)&bits[2];
631 pobits[0] = (fd_set *)&bits[3];
632 pobits[1] = (fd_set *)&bits[4];
633 pobits[2] = (fd_set *)&bits[5];
634 }
635
636 kqpoll_init(nd);
637
638#define getbits(name, x) \
639 if (name && (error = copyin(name, pibits[x], ni))) \
640 goto done;
641 getbits(in, 0);
642 getbits(ou, 1);
643 getbits(ex, 2);
644#undef getbits
645#ifdef KTRACE1
646 if (ni > 0 && KTRPOINT(p, KTR_STRUCT)((p)->p_p->ps_traceflag & (1<<(8)) &&
((p)->p_flag & 0x00000001) == 0)
) {
647 if (in) ktrfdset(p, pibits[0], ni)ktrstruct((p), "fdset", (pibits[0]), ni);
648 if (ou) ktrfdset(p, pibits[1], ni)ktrstruct((p), "fdset", (pibits[1]), ni);
649 if (ex) ktrfdset(p, pibits[2], ni)ktrstruct((p), "fdset", (pibits[2]), ni);
650 }
651#endif
652
653 if (sigmask)
654 dosigsuspend(p, *sigmask &~ sigcantmask((1U << ((9)-1)) | (1U << ((17)-1))));
655
656 /* Register kqueue events */
657 error = pselregister(p, pibits, pobits, nd, &nevents, &ncollected);
658 if (error != 0)
659 goto done;
660
661 /*
662 * The poll/select family of syscalls has been designed to
663 * block when file descriptors are not available, even if
664 * there's nothing to wait for.
665 */
666 if (nevents == 0 && ncollected == 0) {
667 uint64_t nsecs = INFSLP0xffffffffffffffffULL;
668
669 if (timeout != NULL((void *)0)) {
670 if (!timespecisset(timeout)((timeout)->tv_sec || (timeout)->tv_nsec))
671 goto done;
672 nsecs = MAX(1, MIN(TIMESPEC_TO_NSEC(timeout), MAXTSLP))(((1)>((((TIMESPEC_TO_NSEC(timeout))<((0xffffffffffffffffULL
- 1)))?(TIMESPEC_TO_NSEC(timeout)):((0xffffffffffffffffULL -
1)))))?(1):((((TIMESPEC_TO_NSEC(timeout))<((0xffffffffffffffffULL
- 1)))?(TIMESPEC_TO_NSEC(timeout)):((0xffffffffffffffffULL -
1)))))
;
673 }
674 error = tsleep_nsec(&nowake, PSOCK24 | PCATCH0x100, "kqsel", nsecs);
675 /* select is not restarted after signals... */
676 if (error == ERESTART-1)
677 error = EINTR4;
678 if (error == EWOULDBLOCK35)
679 error = 0;
680 goto done;
681 }
682
683 /* Do not block if registering found pending events. */
684 if (ncollected > 0)
685 timeout = &zerots;
686
687 /* Collect at most `nevents' possibly waiting in kqueue_scan() */
688 kqueue_scan_setup(&scan, p->p_kq);
689 while (nevents > 0) {
690 struct kevent kev[KQ_NEVENTS8];
691 int i, ready, count;
692
693 /* Maximum number of events per iteration */
694 count = MIN(nitems(kev), nevents)((((sizeof((kev)) / sizeof((kev)[0])))<(nevents))?((sizeof
((kev)) / sizeof((kev)[0]))):(nevents))
;
695 ready = kqueue_scan(&scan, count, kev, timeout, p, &error);
696#ifdef KTRACE1
697 if (KTRPOINT(p, KTR_STRUCT)((p)->p_p->ps_traceflag & (1<<(8)) &&
((p)->p_flag & 0x00000001) == 0)
)
698 ktrevent(p, kev, ready)ktrstruct(p, "kevent", kev, (ready) * sizeof(struct kevent));
699#endif
700 /* Convert back events that are ready. */
701 for (i = 0; i < ready && error == 0; i++)
702 error = pselcollect(p, &kev[i], pobits, &ncollected);
703 /*
704 * Stop if there was an error or if we had enough
705 * space to collect all events that were ready.
706 */
707 if (error || ready < count)
708 break;
709
710 nevents -= ready;
711 }
712 kqueue_scan_finish(&scan);
713 *retval = ncollected;
714done:
715#define putbits(name, x) \
716 if (name && (error2 = copyout(pobits[x], name, ni))) \
717 error = error2;
718 if (error == 0) {
719 int error2;
720
721 putbits(in, 0);
722 putbits(ou, 1);
723 putbits(ex, 2);
724#undef putbits
725#ifdef KTRACE1
726 if (ni > 0 && KTRPOINT(p, KTR_STRUCT)((p)->p_p->ps_traceflag & (1<<(8)) &&
((p)->p_flag & 0x00000001) == 0)
) {
727 if (in) ktrfdset(p, pobits[0], ni)ktrstruct((p), "fdset", (pobits[0]), ni);
728 if (ou) ktrfdset(p, pobits[1], ni)ktrstruct((p), "fdset", (pobits[1]), ni);
729 if (ex) ktrfdset(p, pobits[2], ni)ktrstruct((p), "fdset", (pobits[2]), ni);
730 }
731#endif
732 }
733
734 if (pibits[0] != (fd_set *)&bits[0])
735 free(pibits[0], M_TEMP127, 6 * ni);
736
737 kqpoll_done(nd);
738
739 return (error);
740}
741
742/*
743 * Convert fd_set into kqueue events and register them on the
744 * per-thread queue.
745 */
746int
747pselregister(struct proc *p, fd_set *pibits[3], fd_set *pobits[3], int nfd,
748 int *nregistered, int *ncollected)
749{
750 static const int evf[] = { EVFILT_READ(-1), EVFILT_WRITE(-2), EVFILT_EXCEPT(-9) };
751 static const int evff[] = { 0, 0, NOTE_OOB0x0004 };
752 int msk, i, j, fd, nevents = 0, error = 0;
753 struct kevent kev;
754 fd_mask__fd_mask bits;
755
756 for (msk = 0; msk < 3; msk++) {
757 for (i = 0; i < nfd; i += NFDBITS((unsigned)(sizeof(__fd_mask) * 8))) {
758 bits = pibits[msk]->fds_bits[i / NFDBITS((unsigned)(sizeof(__fd_mask) * 8))];
759 while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
760 bits &= ~(1 << j);
761
762 DPRINTFN(2, "select fd %d mask %d serial %lu\n",if (kqpoll_debug > 2) { printf("%s(%d): ", ({struct cpu_info
*__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof
(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->
ps_comm, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0"
: "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self
))); __ci;})->ci_curproc->p_tid); printf("select fd %d mask %d serial %lu\n"
, fd, msk, p->p_kq_serial); }
763 fd, msk, p->p_kq_serial)if (kqpoll_debug > 2) { printf("%s(%d): ", ({struct cpu_info
*__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof
(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->
ps_comm, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0"
: "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self
))); __ci;})->ci_curproc->p_tid); printf("select fd %d mask %d serial %lu\n"
, fd, msk, p->p_kq_serial); }
;
764 EV_SET(&kev, fd, evf[msk],do { struct kevent *__kevp = (&kev); (__kevp)->ident =
(fd); (__kevp)->filter = (evf[msk]); (__kevp)->flags =
(0x0001|0x0004|0x0800); (__kevp)->fflags = (evff[msk]); (
__kevp)->data = (0); (__kevp)->udata = ((void *)(p->
p_kq_serial)); } while(0)
765 EV_ADD|EV_ENABLE|__EV_SELECT,do { struct kevent *__kevp = (&kev); (__kevp)->ident =
(fd); (__kevp)->filter = (evf[msk]); (__kevp)->flags =
(0x0001|0x0004|0x0800); (__kevp)->fflags = (evff[msk]); (
__kevp)->data = (0); (__kevp)->udata = ((void *)(p->
p_kq_serial)); } while(0)
766 evff[msk], 0, (void *)(p->p_kq_serial))do { struct kevent *__kevp = (&kev); (__kevp)->ident =
(fd); (__kevp)->filter = (evf[msk]); (__kevp)->flags =
(0x0001|0x0004|0x0800); (__kevp)->fflags = (evff[msk]); (
__kevp)->data = (0); (__kevp)->udata = ((void *)(p->
p_kq_serial)); } while(0)
;
767#ifdef KTRACE1
768 if (KTRPOINT(p, KTR_STRUCT)((p)->p_p->ps_traceflag & (1<<(8)) &&
((p)->p_flag & 0x00000001) == 0)
)
769 ktrevent(p, &kev, 1)ktrstruct(p, "kevent", &kev, (1) * sizeof(struct kevent));
770#endif
771 error = kqueue_register(p->p_kq, &kev, p);
772 switch (error) {
773 case 0:
774 nevents++;
775 /* FALLTHROUGH */
776 case EOPNOTSUPP45:/* No underlying kqfilter */
777 case EINVAL22: /* Unimplemented filter */
778 case EPERM1: /* Specific to FIFO and
779 * __EV_SELECT */
780 error = 0;
781 break;
782 case EPIPE32: /* Specific to pipes */
783 KASSERT(kev.filter == EVFILT_WRITE)((kev.filter == (-2)) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/kern/sys_generic.c"
, 783, "kev.filter == EVFILT_WRITE"))
;
784 FD_SET(kev.ident, pobits[1])__fd_set((kev.ident), (pobits[1]));
785 (*ncollected)++;
786 error = 0;
Value stored to 'error' is never read
787 break;
788 case ENXIO6: /* Device has been detached */
789 default:
790 goto bad;
791 }
792 }
793 }
794 }
795
796 *nregistered = nevents;
797 return (0);
798bad:
799 DPRINTFN(0, "select fd %u filt %d error %d\n", (int)kev.ident,if (kqpoll_debug > 0) { printf("%s(%d): ", ({struct cpu_info
*__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof
(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->
ps_comm, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0"
: "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self
))); __ci;})->ci_curproc->p_tid); printf("select fd %u filt %d error %d\n"
, (int)kev.ident, kev.filter, error); }
800 kev.filter, error)if (kqpoll_debug > 0) { printf("%s(%d): ", ({struct cpu_info
*__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof
(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->
ps_comm, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0"
: "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self
))); __ci;})->ci_curproc->p_tid); printf("select fd %u filt %d error %d\n"
, (int)kev.ident, kev.filter, error); }
;
801 return (error);
802}
803
804/*
805 * Convert given kqueue event into corresponding select(2) bit.
806 */
807int
808pselcollect(struct proc *p, struct kevent *kevp, fd_set *pobits[3],
809 int *ncollected)
810{
811 if ((unsigned long)kevp->udata != p->p_kq_serial) {
812 panic("%s: spurious kevp %p fd %d udata 0x%lx serial 0x%lx",
813 __func__, kevp, (int)kevp->ident,
814 (unsigned long)kevp->udata, p->p_kq_serial);
815 }
816
817 if (kevp->flags & EV_ERROR0x4000) {
818 DPRINTFN(2, "select fd %d filt %d error %d\n",if (kqpoll_debug > 2) { printf("%s(%d): ", ({struct cpu_info
*__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof
(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->
ps_comm, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0"
: "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self
))); __ci;})->ci_curproc->p_tid); printf("select fd %d filt %d error %d\n"
, (int)kevp->ident, kevp->filter, (int)kevp->data); }
819 (int)kevp->ident, kevp->filter, (int)kevp->data)if (kqpoll_debug > 2) { printf("%s(%d): ", ({struct cpu_info
*__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof
(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->
ps_comm, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0"
: "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self
))); __ci;})->ci_curproc->p_tid); printf("select fd %d filt %d error %d\n"
, (int)kevp->ident, kevp->filter, (int)kevp->data); }
;
820 return (kevp->data);
821 }
822
823 switch (kevp->filter) {
824 case EVFILT_READ(-1):
825 FD_SET(kevp->ident, pobits[0])__fd_set((kevp->ident), (pobits[0]));
826 break;
827 case EVFILT_WRITE(-2):
828 FD_SET(kevp->ident, pobits[1])__fd_set((kevp->ident), (pobits[1]));
829 break;
830 case EVFILT_EXCEPT(-9):
831 FD_SET(kevp->ident, pobits[2])__fd_set((kevp->ident), (pobits[2]));
832 break;
833 default:
834 KASSERT(0)((0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/kern/sys_generic.c"
, 834, "0"))
;
835 }
836 (*ncollected)++;
837
838 DPRINTFN(2, "select fd %d filt %d\n", (int)kevp->ident, kevp->filter)if (kqpoll_debug > 2) { printf("%s(%d): ", ({struct cpu_info
*__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof
(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->
ps_comm, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0"
: "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self
))); __ci;})->ci_curproc->p_tid); printf("select fd %d filt %d\n"
, (int)kevp->ident, kevp->filter); }
;
839 return (0);
840}
841
842int
843seltrue(dev_t dev, int events, struct proc *p)
844{
845
846 return (events & (POLLIN0x0001 | POLLOUT0x0004 | POLLRDNORM0x0040 | POLLWRNORM0x0004));
847}
848
849int
850selfalse(dev_t dev, int events, struct proc *p)
851{
852
853 return (0);
854}
855
856/*
857 * Record a select request.
858 */
859void
860selrecord(struct proc *selector, struct selinfo *sip)
861{
862 struct proc *p;
863 pid_t mytid;
864
865 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/kern/sys_generic.c"
, 865, "_kernel_lock_held()"))
;
866
867 mytid = selector->p_tid;
868 if (sip->si_seltid == mytid)
869 return;
870 if (sip->si_seltid && (p = tfind(sip->si_seltid)) &&
871 p->p_wchan == (caddr_t)&selwait)
872 sip->si_flags |= SI_COLL0x0001;
873 else
874 sip->si_seltid = mytid;
875}
876
877/*
878 * Do a wakeup when a selectable event occurs.
879 */
880void
881selwakeup(struct selinfo *sip)
882{
883 KERNEL_LOCK()_kernel_lock();
884 KNOTE(&sip->si_note, NOTE_SUBMIT)do { struct klist *__list = (&sip->si_note); if (__list
!= ((void *)0)) knote(__list, 0x01000000); } while (0)
;
885 doselwakeup(sip);
886 KERNEL_UNLOCK()_kernel_unlock();
887}
888
889void
890doselwakeup(struct selinfo *sip)
891{
892 struct proc *p;
893
894 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/kern/sys_generic.c"
, 894, "_kernel_lock_held()"))
;
895
896 if (sip->si_seltid == 0)
897 return;
898 if (sip->si_flags & SI_COLL0x0001) {
899 nselcoll++;
900 sip->si_flags &= ~SI_COLL0x0001;
901 wakeup(&selwait);
902 }
903 p = tfind(sip->si_seltid);
904 sip->si_seltid = 0;
905 if (p != NULL((void *)0)) {
906 if (wakeup_proc(p, &selwait)) {
907 /* nothing else to do */
908 } else if (p->p_flag & P_SELECT0x00000040)
909 atomic_clearbits_intx86_atomic_clearbits_u32(&p->p_flag, P_SELECT0x00000040);
910 }
911}
912
913void
914pollscan(struct proc *p, struct pollfd *pl, u_int nfd, register_t *retval)
915{
916 struct filedesc *fdp = p->p_fd;
917 struct file *fp;
918 u_int i;
919 int n = 0;
920
921 for (i = 0; i < nfd; i++, pl++) {
922 /* Check the file descriptor. */
923 if (pl->fd < 0) {
924 pl->revents = 0;
925 continue;
926 }
927 if ((fp = fd_getfile(fdp, pl->fd)) == NULL((void *)0)) {
928 pl->revents = POLLNVAL0x0020;
929 n++;
930 continue;
931 }
932 pl->revents = (*fp->f_ops->fo_poll)(fp, pl->events, p);
933 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
934 if (pl->revents != 0)
935 n++;
936 }
937 *retval = n;
938}
939
940/*
941 * Only copyout the revents field.
942 */
943int
944pollout(struct pollfd *pl, struct pollfd *upl, u_int nfds)
945{
946 int error = 0;
947 u_int i = 0;
948
949 while (!error && i++ < nfds) {
950 error = copyout(&pl->revents, &upl->revents,
951 sizeof(upl->revents));
952 pl++;
953 upl++;
954 }
955
956 return (error);
957}
958
959/*
960 * We are using the same mechanism as select only we encode/decode args
961 * differently.
962 */
963int
964sys_poll(struct proc *p, void *v, register_t *retval)
965{
966 struct sys_poll_args /* {
967 syscallarg(struct pollfd *) fds;
968 syscallarg(u_int) nfds;
969 syscallarg(int) timeout;
970 } */ *uap = v;
971
972 struct timespec ts, *tsp = NULL((void *)0);
973 int msec = SCARG(uap, timeout)((uap)->timeout.le.datum);
974
975 if (msec != INFTIM(-1)) {
976 if (msec < 0)
977 return (EINVAL22);
978 ts.tv_sec = msec / 1000;
979 ts.tv_nsec = (msec - (ts.tv_sec * 1000)) * 1000000;
980 tsp = &ts;
981 }
982
983 return (doppoll(p, SCARG(uap, fds)((uap)->fds.le.datum), SCARG(uap, nfds)((uap)->nfds.le.datum), tsp, NULL((void *)0),
984 retval));
985}
986
987int
988sys_ppoll(struct proc *p, void *v, register_t *retval)
989{
990 struct sys_ppoll_args /* {
991 syscallarg(struct pollfd *) fds;
992 syscallarg(u_int) nfds;
993 syscallarg(const struct timespec *) ts;
994 syscallarg(const sigset_t *) mask;
995 } */ *uap = v;
996
997 int error;
998 struct timespec ts, *tsp = NULL((void *)0);
999 sigset_t ss, *ssp = NULL((void *)0);
1000
1001 if (SCARG(uap, ts)((uap)->ts.le.datum) != NULL((void *)0)) {
1002 if ((error = copyin(SCARG(uap, ts)((uap)->ts.le.datum), &ts, sizeof ts)) != 0)
1003 return (error);
1004#ifdef KTRACE1
1005 if (KTRPOINT(p, KTR_STRUCT)((p)->p_p->ps_traceflag & (1<<(8)) &&
((p)->p_flag & 0x00000001) == 0)
)
1006 ktrreltimespec(p, &ts)ktrstruct((p), "reltimespec", (&ts), sizeof(struct timespec
))
;
1007#endif
1008 if (ts.tv_sec < 0 || !timespecisvalid(&ts)((&ts)->tv_nsec >= 0 && (&ts)->tv_nsec
< 1000000000L)
)
1009 return (EINVAL22);
1010 tsp = &ts;
1011 }
1012
1013 if (SCARG(uap, mask)((uap)->mask.le.datum) != NULL((void *)0)) {
1014 if ((error = copyin(SCARG(uap, mask)((uap)->mask.le.datum), &ss, sizeof ss)) != 0)
1015 return (error);
1016 ssp = &ss;
1017 }
1018
1019 return (doppoll(p, SCARG(uap, fds)((uap)->fds.le.datum), SCARG(uap, nfds)((uap)->nfds.le.datum), tsp, ssp,
1020 retval));
1021}
1022
1023int
1024doppoll(struct proc *p, struct pollfd *fds, u_int nfds,
1025 struct timespec *timeout, const sigset_t *sigmask, register_t *retval)
1026{
1027 size_t sz;
1028 struct pollfd pfds[4], *pl = pfds;
1029 struct timespec elapsed, start, stop;
1030 uint64_t nsecs;
1031 int ncoll, i, s, error;
1032
1033 /* Standards say no more than MAX_OPEN; this is possibly better. */
1034 if (nfds > min((int)lim_cur(RLIMIT_NOFILE8), maxfiles))
1035 return (EINVAL22);
1036
1037 /* optimize for the default case, of a small nfds value */
1038 if (nfds > nitems(pfds)(sizeof((pfds)) / sizeof((pfds)[0]))) {
1039 pl = mallocarray(nfds, sizeof(*pl), M_TEMP127,
1040 M_WAITOK0x0001 | M_CANFAIL0x0004);
1041 if (pl == NULL((void *)0))
1042 return (EINVAL22);
1043 }
1044
1045 sz = nfds * sizeof(*pl);
1046
1047 if ((error = copyin(fds, pl, sz)) != 0)
1048 goto bad;
1049
1050 for (i = 0; i < nfds; i++) {
1051 pl[i].events &= ~POLL_NOHUP0x1000;
1052 pl[i].revents = 0;
1053 }
1054
1055 if (sigmask)
1056 dosigsuspend(p, *sigmask &~ sigcantmask((1U << ((9)-1)) | (1U << ((17)-1))));
1057
1058retry:
1059 ncoll = nselcoll;
1060 atomic_setbits_intx86_atomic_setbits_u32(&p->p_flag, P_SELECT0x00000040);
1061 pollscan(p, pl, nfds, retval);
1062 if (*retval)
1063 goto done;
1064 if (timeout == NULL((void *)0) || timespecisset(timeout)((timeout)->tv_sec || (timeout)->tv_nsec)) {
1065 if (timeout != NULL((void *)0)) {
1066 getnanouptime(&start);
1067 nsecs = MIN(TIMESPEC_TO_NSEC(timeout), MAXTSLP)(((TIMESPEC_TO_NSEC(timeout))<((0xffffffffffffffffULL - 1)
))?(TIMESPEC_TO_NSEC(timeout)):((0xffffffffffffffffULL - 1)))
;
1068 } else
1069 nsecs = INFSLP0xffffffffffffffffULL;
1070 s = splhigh()splraise(0xd);
1071 if ((p->p_flag & P_SELECT0x00000040) == 0 || nselcoll != ncoll) {
1072 splx(s)spllower(s);
1073 goto retry;
1074 }
1075 atomic_clearbits_intx86_atomic_clearbits_u32(&p->p_flag, P_SELECT0x00000040);
1076 error = tsleep_nsec(&selwait, PSOCK24 | PCATCH0x100, "poll", nsecs);
1077 splx(s)spllower(s);
1078 if (timeout != NULL((void *)0)) {
1079 getnanouptime(&stop);
1080 timespecsub(&stop, &start, &elapsed)do { (&elapsed)->tv_sec = (&stop)->tv_sec - (&
start)->tv_sec; (&elapsed)->tv_nsec = (&stop)->
tv_nsec - (&start)->tv_nsec; if ((&elapsed)->tv_nsec
< 0) { (&elapsed)->tv_sec--; (&elapsed)->tv_nsec
+= 1000000000L; } } while (0)
;
1081 timespecsub(timeout, &elapsed, timeout)do { (timeout)->tv_sec = (timeout)->tv_sec - (&elapsed
)->tv_sec; (timeout)->tv_nsec = (timeout)->tv_nsec -
(&elapsed)->tv_nsec; if ((timeout)->tv_nsec < 0
) { (timeout)->tv_sec--; (timeout)->tv_nsec += 1000000000L
; } } while (0)
;
1082 if (timeout->tv_sec < 0)
1083 timespecclear(timeout)(timeout)->tv_sec = (timeout)->tv_nsec = 0;
1084 }
1085 if (error == 0 || error == EWOULDBLOCK35)
1086 goto retry;
1087 }
1088
1089done:
1090 atomic_clearbits_intx86_atomic_clearbits_u32(&p->p_flag, P_SELECT0x00000040);
1091 /*
1092 * NOTE: poll(2) is not restarted after a signal and EWOULDBLOCK is
1093 * ignored (since the whole point is to see what would block).
1094 */
1095 switch (error) {
1096 case ERESTART-1:
1097 error = pollout(pl, fds, nfds);
1098 if (error == 0)
1099 error = EINTR4;
1100 break;
1101 case EWOULDBLOCK35:
1102 case 0:
1103 error = pollout(pl, fds, nfds);
1104 break;
1105 }
1106#ifdef KTRACE1
1107 if (KTRPOINT(p, KTR_STRUCT)((p)->p_p->ps_traceflag & (1<<(8)) &&
((p)->p_flag & 0x00000001) == 0)
)
1108 ktrpollfd(p, pl, nfds)ktrstruct(p, "pollfd", pl, (nfds) * sizeof(struct pollfd));
1109#endif /* KTRACE */
1110bad:
1111 if (pl != pfds)
1112 free(pl, M_TEMP127, sz);
1113 return (error);
1114}
1115
1116/*
1117 * utrace system call
1118 */
1119int
1120sys_utrace(struct proc *curp, void *v, register_t *retval)
1121{
1122#ifdef KTRACE1
1123 struct sys_utrace_args /* {
1124 syscallarg(const char *) label;
1125 syscallarg(const void *) addr;
1126 syscallarg(size_t) len;
1127 } */ *uap = v;
1128
1129 return (ktruser(curp, SCARG(uap, label)((uap)->label.le.datum), SCARG(uap, addr)((uap)->addr.le.datum),
1130 SCARG(uap, len)((uap)->len.le.datum)));
1131#else
1132 return (0);
1133#endif
1134}