Bug Summary

File:kern/kern_descrip.c
Warning:line 1404, column 11
Copies out a struct with uncleared padding (>= 4 bytes)

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-unknown-freebsd11.2 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name kern_descrip.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 -mrelocation-model static -mthread-model posix -mdisable-fp-elim -relaxed-aliasing -masm-verbose -mconstructor-aliases -ffreestanding -mcode-model kernel -target-cpu x86-64 -target-feature -mmx -target-feature -sse -target-feature -aes -target-feature -avx -disable-red-zone -no-implicit-float -dwarf-column-info -debugger-tuning=gdb -nostdsysteminc -nobuiltininc -resource-dir /root/kernel-uninitialized-memory-checker/build/lib/clang/8.0.0 -include opt_global.h -I . -I /root/freebsd/sys -I /root/freebsd/sys/contrib/ck/include -I /root/freebsd/sys/contrib/libfdt -D _KERNEL -D HAVE_KERNEL_OPTION_HEADERS -D __printf__=__freebsd_kprintf__ -O2 -Wno-pointer-sign -Wno-unknown-pragmas -Wno-error-tautological-compare -Wno-error-empty-body -Wno-error-parentheses-equality -Wno-error-unused-function -Wno-error-pointer-sign -Wno-error-shift-negative-value -Wno-address-of-packed-member -std=iso9899:1999 -fdebug-compilation-dir /usr/obj/root/freebsd/amd64.amd64/sys/GENERIC -ferror-limit 19 -fmessage-length 0 -fwrapv -stack-protector 1 -fobjc-runtime=gnustep -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-checker alpha.security.KernelMemoryDisclosure -analyzer-disable-checker core,unix,deadcode,nullability -analyzer-output=html -o /root/analyzer/2018-12-28-044519-76292-1 -x c /root/freebsd/sys/kern/kern_descrip.c -faddrsig
1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1982, 1986, 1989, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc.
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 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)kern_descrip.c 8.6 (Berkeley) 4/19/94
37 */
38
39#include <sys/cdefs.h>
40__FBSDID("$FreeBSD$")__asm__(".ident\t\"" "$FreeBSD$" "\"");
41
42#include "opt_capsicum.h"
43#include "opt_ddb.h"
44#include "opt_ktrace.h"
45
46#include <sys/param.h>
47#include <sys/systm.h>
48
49#include <sys/capsicum.h>
50#include <sys/conf.h>
51#include <sys/fcntl.h>
52#include <sys/file.h>
53#include <sys/filedesc.h>
54#include <sys/filio.h>
55#include <sys/jail.h>
56#include <sys/kernel.h>
57#include <sys/limits.h>
58#include <sys/lock.h>
59#include <sys/malloc.h>
60#include <sys/mount.h>
61#include <sys/mutex.h>
62#include <sys/namei.h>
63#include <sys/selinfo.h>
64#include <sys/priv.h>
65#include <sys/proc.h>
66#include <sys/protosw.h>
67#include <sys/racct.h>
68#include <sys/resourcevar.h>
69#include <sys/sbuf.h>
70#include <sys/signalvar.h>
71#include <sys/kdb.h>
72#include <sys/stat.h>
73#include <sys/sx.h>
74#include <sys/syscallsubr.h>
75#include <sys/sysctl.h>
76#include <sys/sysproto.h>
77#include <sys/unistd.h>
78#include <sys/user.h>
79#include <sys/vnode.h>
80#ifdef KTRACE1
81#include <sys/ktrace.h>
82#endif
83
84#include <net/vnet.h>
85
86#include <security/audit/audit.h>
87
88#include <vm/uma.h>
89#include <vm/vm.h>
90
91#include <ddb/ddb.h>
92
93static MALLOC_DEFINE(M_FILEDESC, "filedesc", "Open file descriptor table")struct malloc_type M_FILEDESC[1] = { { ((void *)0), 877983977
, "filedesc", ((void *)0) } }; static struct sysinit M_FILEDESC_init_sys_init
= { SI_SUB_KMEM, SI_ORDER_THIRD, (sysinit_cfunc_t)(sysinit_nfunc_t
)malloc_init, ((void *)(M_FILEDESC)) }; __asm__(".globl " "__start_set_sysinit_set"
); __asm__(".globl " "__stop_set_sysinit_set"); static void const
* __set_sysinit_set_sym_M_FILEDESC_init_sys_init __attribute__
((__section__("set_" "sysinit_set"))) __attribute__((__used__
)) = &(M_FILEDESC_init_sys_init); static struct sysinit M_FILEDESC_uninit_sys_uninit
= { SI_SUB_KMEM, SI_ORDER_ANY, (sysinit_cfunc_t)(sysinit_nfunc_t
)malloc_uninit, ((void *)(M_FILEDESC)) }; __asm__(".globl " "__start_set_sysuninit_set"
); __asm__(".globl " "__stop_set_sysuninit_set"); static void
const * __set_sysuninit_set_sym_M_FILEDESC_uninit_sys_uninit
__attribute__((__section__("set_" "sysuninit_set"))) __attribute__
((__used__)) = &(M_FILEDESC_uninit_sys_uninit)
;
94static MALLOC_DEFINE(M_FILEDESC_TO_LEADER, "filedesc_to_leader",struct malloc_type M_FILEDESC_TO_LEADER[1] = { { ((void *)0),
877983977, "filedesc_to_leader", ((void *)0) } }; static struct
sysinit M_FILEDESC_TO_LEADER_init_sys_init = { SI_SUB_KMEM, SI_ORDER_THIRD
, (sysinit_cfunc_t)(sysinit_nfunc_t)malloc_init, ((void *)(M_FILEDESC_TO_LEADER
)) }; __asm__(".globl " "__start_set_sysinit_set"); __asm__(".globl "
"__stop_set_sysinit_set"); static void const * __set_sysinit_set_sym_M_FILEDESC_TO_LEADER_init_sys_init
__attribute__((__section__("set_" "sysinit_set"))) __attribute__
((__used__)) = &(M_FILEDESC_TO_LEADER_init_sys_init); static
struct sysinit M_FILEDESC_TO_LEADER_uninit_sys_uninit = { SI_SUB_KMEM
, SI_ORDER_ANY, (sysinit_cfunc_t)(sysinit_nfunc_t)malloc_uninit
, ((void *)(M_FILEDESC_TO_LEADER)) }; __asm__(".globl " "__start_set_sysuninit_set"
); __asm__(".globl " "__stop_set_sysuninit_set"); static void
const * __set_sysuninit_set_sym_M_FILEDESC_TO_LEADER_uninit_sys_uninit
__attribute__((__section__("set_" "sysuninit_set"))) __attribute__
((__used__)) = &(M_FILEDESC_TO_LEADER_uninit_sys_uninit)
95 "file desc to leader structures")struct malloc_type M_FILEDESC_TO_LEADER[1] = { { ((void *)0),
877983977, "filedesc_to_leader", ((void *)0) } }; static struct
sysinit M_FILEDESC_TO_LEADER_init_sys_init = { SI_SUB_KMEM, SI_ORDER_THIRD
, (sysinit_cfunc_t)(sysinit_nfunc_t)malloc_init, ((void *)(M_FILEDESC_TO_LEADER
)) }; __asm__(".globl " "__start_set_sysinit_set"); __asm__(".globl "
"__stop_set_sysinit_set"); static void const * __set_sysinit_set_sym_M_FILEDESC_TO_LEADER_init_sys_init
__attribute__((__section__("set_" "sysinit_set"))) __attribute__
((__used__)) = &(M_FILEDESC_TO_LEADER_init_sys_init); static
struct sysinit M_FILEDESC_TO_LEADER_uninit_sys_uninit = { SI_SUB_KMEM
, SI_ORDER_ANY, (sysinit_cfunc_t)(sysinit_nfunc_t)malloc_uninit
, ((void *)(M_FILEDESC_TO_LEADER)) }; __asm__(".globl " "__start_set_sysuninit_set"
); __asm__(".globl " "__stop_set_sysuninit_set"); static void
const * __set_sysuninit_set_sym_M_FILEDESC_TO_LEADER_uninit_sys_uninit
__attribute__((__section__("set_" "sysuninit_set"))) __attribute__
((__used__)) = &(M_FILEDESC_TO_LEADER_uninit_sys_uninit)
;
96static MALLOC_DEFINE(M_SIGIO, "sigio", "sigio structures")struct malloc_type M_SIGIO[1] = { { ((void *)0), 877983977, "sigio"
, ((void *)0) } }; static struct sysinit M_SIGIO_init_sys_init
= { SI_SUB_KMEM, SI_ORDER_THIRD, (sysinit_cfunc_t)(sysinit_nfunc_t
)malloc_init, ((void *)(M_SIGIO)) }; __asm__(".globl " "__start_set_sysinit_set"
); __asm__(".globl " "__stop_set_sysinit_set"); static void const
* __set_sysinit_set_sym_M_SIGIO_init_sys_init __attribute__(
(__section__("set_" "sysinit_set"))) __attribute__((__used__)
) = &(M_SIGIO_init_sys_init); static struct sysinit M_SIGIO_uninit_sys_uninit
= { SI_SUB_KMEM, SI_ORDER_ANY, (sysinit_cfunc_t)(sysinit_nfunc_t
)malloc_uninit, ((void *)(M_SIGIO)) }; __asm__(".globl " "__start_set_sysuninit_set"
); __asm__(".globl " "__stop_set_sysuninit_set"); static void
const * __set_sysuninit_set_sym_M_SIGIO_uninit_sys_uninit __attribute__
((__section__("set_" "sysuninit_set"))) __attribute__((__used__
)) = &(M_SIGIO_uninit_sys_uninit)
;
97MALLOC_DEFINE(M_FILECAPS, "filecaps", "descriptor capabilities")struct malloc_type M_FILECAPS[1] = { { ((void *)0), 877983977
, "filecaps", ((void *)0) } }; static struct sysinit M_FILECAPS_init_sys_init
= { SI_SUB_KMEM, SI_ORDER_THIRD, (sysinit_cfunc_t)(sysinit_nfunc_t
)malloc_init, ((void *)(M_FILECAPS)) }; __asm__(".globl " "__start_set_sysinit_set"
); __asm__(".globl " "__stop_set_sysinit_set"); static void const
* __set_sysinit_set_sym_M_FILECAPS_init_sys_init __attribute__
((__section__("set_" "sysinit_set"))) __attribute__((__used__
)) = &(M_FILECAPS_init_sys_init); static struct sysinit M_FILECAPS_uninit_sys_uninit
= { SI_SUB_KMEM, SI_ORDER_ANY, (sysinit_cfunc_t)(sysinit_nfunc_t
)malloc_uninit, ((void *)(M_FILECAPS)) }; __asm__(".globl " "__start_set_sysuninit_set"
); __asm__(".globl " "__stop_set_sysuninit_set"); static void
const * __set_sysuninit_set_sym_M_FILECAPS_uninit_sys_uninit
__attribute__((__section__("set_" "sysuninit_set"))) __attribute__
((__used__)) = &(M_FILECAPS_uninit_sys_uninit)
;
98
99MALLOC_DECLARE(M_FADVISE)extern struct malloc_type M_FADVISE[1];
100
101static __read_mostly__attribute__((__section__(".data.read_mostly"))) uma_zone_t file_zone;
102static __read_mostly__attribute__((__section__(".data.read_mostly"))) uma_zone_t filedesc0_zone;
103
104static int closefp(struct filedesc *fdp, int fd, struct file *fp,
105 struct thread *td, int holdleaders);
106static int fd_first_free(struct filedesc *fdp, int low, int size);
107static int fd_last_used(struct filedesc *fdp, int size);
108static void fdgrowtable(struct filedesc *fdp, int nfd);
109static void fdgrowtable_exp(struct filedesc *fdp, int nfd);
110static void fdunused(struct filedesc *fdp, int fd);
111static void fdused(struct filedesc *fdp, int fd);
112static int getmaxfd(struct thread *td);
113static u_long *filecaps_copy_prep(const struct filecaps *src);
114static void filecaps_copy_finish(const struct filecaps *src,
115 struct filecaps *dst, u_long *ioctls);
116static u_long *filecaps_free_prep(struct filecaps *fcaps);
117static void filecaps_free_finish(u_long *ioctls);
118
119/*
120 * Each process has:
121 *
122 * - An array of open file descriptors (fd_ofiles)
123 * - An array of file flags (fd_ofileflags)
124 * - A bitmap recording which descriptors are in use (fd_map)
125 *
126 * A process starts out with NDFILE descriptors. The value of NDFILE has
127 * been selected based the historical limit of 20 open files, and an
128 * assumption that the majority of processes, especially short-lived
129 * processes like shells, will never need more.
130 *
131 * If this initial allocation is exhausted, a larger descriptor table and
132 * map are allocated dynamically, and the pointers in the process's struct
133 * filedesc are updated to point to those. This is repeated every time
134 * the process runs out of file descriptors (provided it hasn't hit its
135 * resource limit).
136 *
137 * Since threads may hold references to individual descriptor table
138 * entries, the tables are never freed. Instead, they are placed on a
139 * linked list and freed only when the struct filedesc is released.
140 */
141#define NDFILE20 20
142#define NDSLOTSIZEsizeof(u_long) sizeof(NDSLOTTYPEu_long)
143#define NDENTRIES(sizeof(u_long) * 8) (NDSLOTSIZEsizeof(u_long) * __CHAR_BIT8)
144#define NDSLOT(x)((x) / (sizeof(u_long) * 8)) ((x) / NDENTRIES(sizeof(u_long) * 8))
145#define NDBIT(x)((u_long)1 << ((x) % (sizeof(u_long) * 8))) ((NDSLOTTYPEu_long)1 << ((x) % NDENTRIES(sizeof(u_long) * 8)))
146#define NDSLOTS(x)(((x) + (sizeof(u_long) * 8) - 1) / (sizeof(u_long) * 8)) (((x) + NDENTRIES(sizeof(u_long) * 8) - 1) / NDENTRIES(sizeof(u_long) * 8))
147
148/*
149 * SLIST entry used to keep track of ofiles which must be reclaimed when
150 * the process exits.
151 */
152struct freetable {
153 struct fdescenttbl *ft_table;
154 SLIST_ENTRY(freetable)struct { struct freetable *sle_next; } ft_next;
155};
156
157/*
158 * Initial allocation: a filedesc structure + the head of SLIST used to
159 * keep track of old ofiles + enough space for NDFILE descriptors.
160 */
161
162struct fdescenttbl0 {
163 int fdt_nfiles;
164 struct filedescent fdt_ofiles[NDFILE20];
165};
166
167struct filedesc0 {
168 struct filedesc fd_fd;
169 SLIST_HEAD(, freetable)struct { struct freetable *slh_first; } fd_free;
170 struct fdescenttbl0 fd_dfiles;
171 NDSLOTTYPEu_long fd_dmap[NDSLOTS(NDFILE)(((20) + (sizeof(u_long) * 8) - 1) / (sizeof(u_long) * 8))];
172};
173
174/*
175 * Descriptor management.
176 */
177volatile int __exclusive_cache_line__attribute__((__aligned__((1 << 6)))) __attribute__((__section__
(".data.exclusive_cache_line")))
openfiles; /* actual number of open files */
178struct mtx sigio_lock; /* mtx to protect pointers to sigio */
179void __read_mostly__attribute__((__section__(".data.read_mostly"))) (*mq_fdclose)(struct thread *td, int fd, struct file *fp);
180
181/*
182 * If low >= size, just return low. Otherwise find the first zero bit in the
183 * given bitmap, starting at low and not exceeding size - 1. Return size if
184 * not found.
185 */
186static int
187fd_first_free(struct filedesc *fdp, int low, int size)
188{
189 NDSLOTTYPEu_long *map = fdp->fd_map;
190 NDSLOTTYPEu_long mask;
191 int off, maxoff;
192
193 if (low >= size)
194 return (low);
195
196 off = NDSLOT(low)((low) / (sizeof(u_long) * 8));
197 if (low % NDENTRIES(sizeof(u_long) * 8)) {
198 mask = ~(~(NDSLOTTYPEu_long)0 >> (NDENTRIES(sizeof(u_long) * 8) - (low % NDENTRIES(sizeof(u_long) * 8))));
199 if ((mask &= ~map[off]) != 0UL)
200 return (off * NDENTRIES(sizeof(u_long) * 8) + ffsl(mask) - 1);
201 ++off;
202 }
203 for (maxoff = NDSLOTS(size)(((size) + (sizeof(u_long) * 8) - 1) / (sizeof(u_long) * 8)); off < maxoff; ++off)
204 if (map[off] != ~0UL)
205 return (off * NDENTRIES(sizeof(u_long) * 8) + ffsl(~map[off]) - 1);
206 return (size);
207}
208
209/*
210 * Find the highest non-zero bit in the given bitmap, starting at 0 and
211 * not exceeding size - 1. Return -1 if not found.
212 */
213static int
214fd_last_used(struct filedesc *fdp, int size)
215{
216 NDSLOTTYPEu_long *map = fdp->fd_map;
217 NDSLOTTYPEu_long mask;
218 int off, minoff;
219
220 off = NDSLOT(size)((size) / (sizeof(u_long) * 8));
221 if (size % NDENTRIES(sizeof(u_long) * 8)) {
222 mask = ~(~(NDSLOTTYPEu_long)0 << (size % NDENTRIES(sizeof(u_long) * 8)));
223 if ((mask &= map[off]) != 0)
224 return (off * NDENTRIES(sizeof(u_long) * 8) + flsl(mask) - 1);
225 --off;
226 }
227 for (minoff = NDSLOT(0)((0) / (sizeof(u_long) * 8)); off >= minoff; --off)
228 if (map[off] != 0)
229 return (off * NDENTRIES(sizeof(u_long) * 8) + flsl(map[off]) - 1);
230 return (-1);
231}
232
233static int
234fdisused(struct filedesc *fdp, int fd)
235{
236
237 KASSERT(fd >= 0 && fd < fdp->fd_nfiles,do { if (__builtin_expect((!(fd >= 0 && fd < fdp
->fd_files->fdt_nfiles)), 0)) panic ("file descriptor %d out of range (0, %d)"
, fd, fdp->fd_files->fdt_nfiles); } while (0)
238 ("file descriptor %d out of range (0, %d)", fd, fdp->fd_nfiles))do { if (__builtin_expect((!(fd >= 0 && fd < fdp
->fd_files->fdt_nfiles)), 0)) panic ("file descriptor %d out of range (0, %d)"
, fd, fdp->fd_files->fdt_nfiles); } while (0)
;
239
240 return ((fdp->fd_map[NDSLOT(fd)((fd) / (sizeof(u_long) * 8))] & NDBIT(fd)((u_long)1 << ((fd) % (sizeof(u_long) * 8)))) != 0);
241}
242
243/*
244 * Mark a file descriptor as used.
245 */
246static void
247fdused_init(struct filedesc *fdp, int fd)
248{
249
250 KASSERT(!fdisused(fdp, fd), ("fd=%d is already used", fd))do { if (__builtin_expect((!(!fdisused(fdp, fd))), 0)) panic (
"fd=%d is already used", fd); } while (0)
;
251
252 fdp->fd_map[NDSLOT(fd)((fd) / (sizeof(u_long) * 8))] |= NDBIT(fd)((u_long)1 << ((fd) % (sizeof(u_long) * 8)));
253}
254
255static void
256fdused(struct filedesc *fdp, int fd)
257{
258
259 FILEDESC_XLOCK_ASSERT(fdp)_sx_assert(((&(fdp)->fd_sx)), ((0x00000004 | 0x00000010
)), ("/root/freebsd/sys/kern/kern_descrip.c"), (259))
;
260
261 fdused_init(fdp, fd);
262 if (fd > fdp->fd_lastfile)
263 fdp->fd_lastfile = fd;
264 if (fd == fdp->fd_freefile)
265 fdp->fd_freefile++;
266}
267
268/*
269 * Mark a file descriptor as unused.
270 */
271static void
272fdunused(struct filedesc *fdp, int fd)
273{
274
275 FILEDESC_XLOCK_ASSERT(fdp)_sx_assert(((&(fdp)->fd_sx)), ((0x00000004 | 0x00000010
)), ("/root/freebsd/sys/kern/kern_descrip.c"), (275))
;
276
277 KASSERT(fdisused(fdp, fd), ("fd=%d is already unused", fd))do { if (__builtin_expect((!(fdisused(fdp, fd))), 0)) panic (
"fd=%d is already unused", fd); } while (0)
;
278 KASSERT(fdp->fd_ofiles[fd].fde_file == NULL,do { if (__builtin_expect((!(fdp->fd_files->fdt_ofiles[
fd].fde_file == ((void *)0))), 0)) panic ("fd=%d is still in use"
, fd); } while (0)
279 ("fd=%d is still in use", fd))do { if (__builtin_expect((!(fdp->fd_files->fdt_ofiles[
fd].fde_file == ((void *)0))), 0)) panic ("fd=%d is still in use"
, fd); } while (0)
;
280
281 fdp->fd_map[NDSLOT(fd)((fd) / (sizeof(u_long) * 8))] &= ~NDBIT(fd)((u_long)1 << ((fd) % (sizeof(u_long) * 8)));
282 if (fd < fdp->fd_freefile)
283 fdp->fd_freefile = fd;
284 if (fd == fdp->fd_lastfile)
285 fdp->fd_lastfile = fd_last_used(fdp, fd);
286}
287
288/*
289 * Free a file descriptor.
290 *
291 * Avoid some work if fdp is about to be destroyed.
292 */
293static inline void
294fdefree_last(struct filedescent *fde)
295{
296
297 filecaps_free(&fde->fde_caps);
298}
299
300static inline void
301fdfree(struct filedesc *fdp, int fd)
302{
303 struct filedescent *fde;
304
305 fde = &fdp->fd_ofilesfd_files->fdt_ofiles[fd];
306#ifdef CAPABILITIES1
307 seq_write_begin(&fde->fde_seq);
308#endif
309 fde->fde_file = NULL((void *)0);
310#ifdef CAPABILITIES1
311 seq_write_end(&fde->fde_seq);
312#endif
313 fdefree_last(fde);
314 fdunused(fdp, fd);
315}
316
317void
318pwd_ensure_dirs(void)
319{
320 struct filedesc *fdp;
321
322 fdp = curproc((__curthread())->td_proc)->p_fd;
323 FILEDESC_XLOCK(fdp)(void)_sx_xlock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (323))
;
324 if (fdp->fd_cdir == NULL((void *)0)) {
325 fdp->fd_cdir = rootvnode;
326 vrefact(rootvnode);
327 }
328 if (fdp->fd_rdir == NULL((void *)0)) {
329 fdp->fd_rdir = rootvnode;
330 vrefact(rootvnode);
331 }
332 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (332))
;
333}
334
335/*
336 * System calls on descriptors.
337 */
338#ifndef _SYS_SYSPROTO_H_
339struct getdtablesize_args {
340 int dummy;
341};
342#endif
343/* ARGSUSED */
344int
345sys_getdtablesize(struct thread *td, struct getdtablesize_args *uap)
346{
347#ifdef RACCT1
348 uint64_t lim;
349#endif
350
351 td->td_retvaltd_uretoff.tdu_retval[0] = getmaxfd(td);
352#ifdef RACCT1
353 PROC_LOCK(td->td_proc)__mtx_lock_flags(&((((&(td->td_proc)->p_mtx))))
->mtx_lock, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (353))
;
354 lim = racct_get_limit(td->td_proc, RACCT_NOFILE7);
355 PROC_UNLOCK(td->td_proc)__mtx_unlock_flags(&((((&(td->td_proc)->p_mtx))
))->mtx_lock, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (355))
;
356 if (lim < td->td_retvaltd_uretoff.tdu_retval[0])
357 td->td_retvaltd_uretoff.tdu_retval[0] = lim;
358#endif
359 return (0);
360}
361
362/*
363 * Duplicate a file descriptor to a particular value.
364 *
365 * Note: keep in mind that a potential race condition exists when closing
366 * descriptors from a shared descriptor table (via rfork).
367 */
368#ifndef _SYS_SYSPROTO_H_
369struct dup2_args {
370 u_int from;
371 u_int to;
372};
373#endif
374/* ARGSUSED */
375int
376sys_dup2(struct thread *td, struct dup2_args *uap)
377{
378
379 return (kern_dup(td, FDDUP_FIXED, 0, (int)uap->from, (int)uap->to));
380}
381
382/*
383 * Duplicate a file descriptor.
384 */
385#ifndef _SYS_SYSPROTO_H_
386struct dup_args {
387 u_int fd;
388};
389#endif
390/* ARGSUSED */
391int
392sys_dup(struct thread *td, struct dup_args *uap)
393{
394
395 return (kern_dup(td, FDDUP_NORMAL, 0, (int)uap->fd, 0));
396}
397
398/*
399 * The file control system call.
400 */
401#ifndef _SYS_SYSPROTO_H_
402struct fcntl_args {
403 int fd;
404 int cmd;
405 long arg;
406};
407#endif
408/* ARGSUSED */
409int
410sys_fcntl(struct thread *td, struct fcntl_args *uap)
411{
412
413 return (kern_fcntl_freebsd(td, uap->fd, uap->cmd, uap->arg));
414}
415
416int
417kern_fcntl_freebsd(struct thread *td, int fd, int cmd, long arg)
418{
419 struct flock fl;
420 struct __oflock ofl;
421 intptr_t arg1;
422 int error, newcmd;
423
424 error = 0;
425 newcmd = cmd;
426 switch (cmd) {
427 case F_OGETLK7:
428 case F_OSETLK8:
429 case F_OSETLKW9:
430 /*
431 * Convert old flock structure to new.
432 */
433 error = copyin((void *)(intptr_t)arg, &ofl, sizeof(ofl));
434 fl.l_start = ofl.l_start;
435 fl.l_len = ofl.l_len;
436 fl.l_pid = ofl.l_pid;
437 fl.l_type = ofl.l_type;
438 fl.l_whence = ofl.l_whence;
439 fl.l_sysid = 0;
440
441 switch (cmd) {
442 case F_OGETLK7:
443 newcmd = F_GETLK11;
444 break;
445 case F_OSETLK8:
446 newcmd = F_SETLK12;
447 break;
448 case F_OSETLKW9:
449 newcmd = F_SETLKW13;
450 break;
451 }
452 arg1 = (intptr_t)&fl;
453 break;
454 case F_GETLK11:
455 case F_SETLK12:
456 case F_SETLKW13:
457 case F_SETLK_REMOTE14:
458 error = copyin((void *)(intptr_t)arg, &fl, sizeof(fl));
459 arg1 = (intptr_t)&fl;
460 break;
461 default:
462 arg1 = arg;
463 break;
464 }
465 if (error)
466 return (error);
467 error = kern_fcntl(td, fd, newcmd, arg1);
468 if (error)
469 return (error);
470 if (cmd == F_OGETLK7) {
471 ofl.l_start = fl.l_start;
472 ofl.l_len = fl.l_len;
473 ofl.l_pid = fl.l_pid;
474 ofl.l_type = fl.l_type;
475 ofl.l_whence = fl.l_whence;
476 error = copyout(&ofl, (void *)(intptr_t)arg, sizeof(ofl));
477 } else if (cmd == F_GETLK11) {
478 error = copyout(&fl, (void *)(intptr_t)arg, sizeof(fl));
479 }
480 return (error);
481}
482
483int
484kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
485{
486 struct filedesc *fdp;
487 struct flock *flp;
488 struct file *fp, *fp2;
489 struct filedescent *fde;
490 struct proc *p;
491 struct vnode *vp;
492 int error, flg, tmp;
493 uint64_t bsize;
494 off_t foffset;
495
496 error = 0;
497 flg = F_POSIX0x040;
498 p = td->td_proc;
499 fdp = p->p_fd;
500
501 AUDIT_ARG_FD(cmd)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fd((cmd)); } while (0)
;
502 AUDIT_ARG_CMD(cmd)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_cmd((cmd)); } while (0)
;
503 switch (cmd) {
504 case F_DUPFD0:
505 tmp = arg;
506 error = kern_dup(td, FDDUP_FCNTL, 0, fd, tmp);
507 break;
508
509 case F_DUPFD_CLOEXEC17:
510 tmp = arg;
511 error = kern_dup(td, FDDUP_FCNTL, FDDUP_FLAG_CLOEXEC0x1, fd, tmp);
512 break;
513
514 case F_DUP2FD10:
515 tmp = arg;
516 error = kern_dup(td, FDDUP_FIXED, 0, fd, tmp);
517 break;
518
519 case F_DUP2FD_CLOEXEC18:
520 tmp = arg;
521 error = kern_dup(td, FDDUP_FIXED, FDDUP_FLAG_CLOEXEC0x1, fd, tmp);
522 break;
523
524 case F_GETFD1:
525 error = EBADF9;
526 FILEDESC_SLOCK(fdp)(void)_sx_slock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (526))
;
527 fde = fdeget_locked(fdp, fd);
528 if (fde != NULL((void *)0)) {
529 td->td_retvaltd_uretoff.tdu_retval[0] =
530 (fde->fde_flags & UF_EXCLOSE0x01) ? FD_CLOEXEC1 : 0;
531 error = 0;
532 }
533 FILEDESC_SUNLOCK(fdp)_sx_sunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (533))
;
534 break;
535
536 case F_SETFD2:
537 error = EBADF9;
538 FILEDESC_XLOCK(fdp)(void)_sx_xlock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (538))
;
539 fde = fdeget_locked(fdp, fd);
540 if (fde != NULL((void *)0)) {
541 fde->fde_flags = (fde->fde_flags & ~UF_EXCLOSE0x01) |
542 (arg & FD_CLOEXEC1 ? UF_EXCLOSE0x01 : 0);
543 error = 0;
544 }
545 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (545))
;
546 break;
547
548 case F_GETFL3:
549 error = fget_fcntl(td, fd, &cap_fcntl_rights, F_GETFL3, &fp);
550 if (error != 0)
551 break;
552 td->td_retvaltd_uretoff.tdu_retval[0] = OFLAGS(fp->f_flag)((fp->f_flag) & 0x00040000 ? (fp->f_flag) : (fp->
f_flag) - 1)
;
553 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
554 break;
555
556 case F_SETFL4:
557 error = fget_fcntl(td, fd, &cap_fcntl_rights, F_SETFL4, &fp);
558 if (error != 0)
559 break;
560 do {
561 tmp = flg = fp->f_flag;
562 tmp &= ~FCNTLFLAGS(0x0008|0x0040|0x0080|0x0004|0x0100|0x0200| 0x00010000);
563 tmp |= FFLAGS(arg & ~O_ACCMODE)((arg & ~0x0003) & 0x00040000 ? (arg & ~0x0003) :
(arg & ~0x0003) + 1)
& FCNTLFLAGS(0x0008|0x0040|0x0080|0x0004|0x0100|0x0200| 0x00010000);
564 } while(atomic_cmpset_int(&fp->f_flag, flg, tmp) == 0);
565 tmp = fp->f_flag & FNONBLOCK0x0004;
566 error = fo_ioctl(fp, FIONBIO((unsigned long) ((0x80000000) | (((sizeof(int)) & ((1 <<
13) - 1)) << 16) | ((('f')) << 8) | ((126))))
, &tmp, td->td_ucred, td);
567 if (error != 0) {
568 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
569 break;
570 }
571 tmp = fp->f_flag & FASYNC0x0040;
572 error = fo_ioctl(fp, FIOASYNC((unsigned long) ((0x80000000) | (((sizeof(int)) & ((1 <<
13) - 1)) << 16) | ((('f')) << 8) | ((125))))
, &tmp, td->td_ucred, td);
573 if (error == 0) {
574 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
575 break;
576 }
577 atomic_clear_int(&fp->f_flag, FNONBLOCK0x0004);
578 tmp = 0;
579 (void)fo_ioctl(fp, FIONBIO((unsigned long) ((0x80000000) | (((sizeof(int)) & ((1 <<
13) - 1)) << 16) | ((('f')) << 8) | ((126))))
, &tmp, td->td_ucred, td);
580 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
581 break;
582
583 case F_GETOWN5:
584 error = fget_fcntl(td, fd, &cap_fcntl_rights, F_GETOWN5, &fp);
585 if (error != 0)
586 break;
587 error = fo_ioctl(fp, FIOGETOWN((unsigned long) ((0x40000000) | (((sizeof(int)) & ((1 <<
13) - 1)) << 16) | ((('f')) << 8) | ((123))))
, &tmp, td->td_ucred, td);
588 if (error == 0)
589 td->td_retvaltd_uretoff.tdu_retval[0] = tmp;
590 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
591 break;
592
593 case F_SETOWN6:
594 error = fget_fcntl(td, fd, &cap_fcntl_rights, F_SETOWN6, &fp);
595 if (error != 0)
596 break;
597 tmp = arg;
598 error = fo_ioctl(fp, FIOSETOWN((unsigned long) ((0x80000000) | (((sizeof(int)) & ((1 <<
13) - 1)) << 16) | ((('f')) << 8) | ((124))))
, &tmp, td->td_ucred, td);
599 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
600 break;
601
602 case F_SETLK_REMOTE14:
603 error = priv_check(td, PRIV_NFS_LOCKD291);
604 if (error)
605 return (error);
606 flg = F_REMOTE0x080;
607 goto do_setlk;
608
609 case F_SETLKW13:
610 flg |= F_WAIT0x010;
611 /* FALLTHROUGH F_SETLK */
612
613 case F_SETLK12:
614 do_setlk:
615 error = fget_unlocked(fdp, fd, &cap_flock_rights, &fp, NULL((void *)0));
616 if (error != 0)
617 break;
618 if (fp->f_type != DTYPE_VNODE1) {
619 error = EBADF9;
620 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
621 break;
622 }
623
624 flp = (struct flock *)arg;
625 if (flp->l_whence == SEEK_CUR1) {
626 foffset = foffset_get(fp);
627 if (foffset < 0 ||
628 (flp->l_start > 0 &&
629 foffset > OFF_MAX0x7fffffffffffffff - flp->l_start)) {
630 error = EOVERFLOW84;
631 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
632 break;
633 }
634 flp->l_start += foffset;
635 }
636
637 vp = fp->f_vnode;
638 switch (flp->l_type) {
639 case F_RDLCK1:
640 if ((fp->f_flag & FREAD0x0001) == 0) {
641 error = EBADF9;
642 break;
643 }
644 if ((p->p_leader->p_flag & P_ADVLOCK0x00001) == 0) {
645 PROC_LOCK(p->p_leader)__mtx_lock_flags(&((((&(p->p_leader)->p_mtx))))
->mtx_lock, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (645))
;
646 p->p_leader->p_flag |= P_ADVLOCK0x00001;
647 PROC_UNLOCK(p->p_leader)__mtx_unlock_flags(&((((&(p->p_leader)->p_mtx))
))->mtx_lock, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (647))
;
648 }
649 error = VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_SETLK12,
650 flp, flg);
651 break;
652 case F_WRLCK3:
653 if ((fp->f_flag & FWRITE0x0002) == 0) {
654 error = EBADF9;
655 break;
656 }
657 if ((p->p_leader->p_flag & P_ADVLOCK0x00001) == 0) {
658 PROC_LOCK(p->p_leader)__mtx_lock_flags(&((((&(p->p_leader)->p_mtx))))
->mtx_lock, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (658))
;
659 p->p_leader->p_flag |= P_ADVLOCK0x00001;
660 PROC_UNLOCK(p->p_leader)__mtx_unlock_flags(&((((&(p->p_leader)->p_mtx))
))->mtx_lock, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (660))
;
661 }
662 error = VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_SETLK12,
663 flp, flg);
664 break;
665 case F_UNLCK2:
666 error = VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_UNLCK2,
667 flp, flg);
668 break;
669 case F_UNLCKSYS4:
670 /*
671 * Temporary api for testing remote lock
672 * infrastructure.
673 */
674 if (flg != F_REMOTE0x080) {
675 error = EINVAL22;
676 break;
677 }
678 error = VOP_ADVLOCK(vp, (caddr_t)p->p_leader,
679 F_UNLCKSYS4, flp, flg);
680 break;
681 default:
682 error = EINVAL22;
683 break;
684 }
685 if (error != 0 || flp->l_type == F_UNLCK2 ||
686 flp->l_type == F_UNLCKSYS4) {
687 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
688 break;
689 }
690
691 /*
692 * Check for a race with close.
693 *
694 * The vnode is now advisory locked (or unlocked, but this case
695 * is not really important) as the caller requested.
696 * We had to drop the filedesc lock, so we need to recheck if
697 * the descriptor is still valid, because if it was closed
698 * in the meantime we need to remove advisory lock from the
699 * vnode - close on any descriptor leading to an advisory
700 * locked vnode, removes that lock.
701 * We will return 0 on purpose in that case, as the result of
702 * successful advisory lock might have been externally visible
703 * already. This is fine - effectively we pretend to the caller
704 * that the closing thread was a bit slower and that the
705 * advisory lock succeeded before the close.
706 */
707 error = fget_unlocked(fdp, fd, &cap_no_rights, &fp2, NULL((void *)0));
708 if (error != 0) {
709 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
710 break;
711 }
712 if (fp != fp2) {
713 flp->l_whence = SEEK_SET0;
714 flp->l_start = 0;
715 flp->l_len = 0;
716 flp->l_type = F_UNLCK2;
717 (void) VOP_ADVLOCK(vp, (caddr_t)p->p_leader,
718 F_UNLCK2, flp, F_POSIX0x040);
719 }
720 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
721 fdrop(fp2, td)(refcount_release(&(fp2)->f_count) ? _fdrop((fp2), (td
)) : _fnoop())
;
722 break;
723
724 case F_GETLK11:
725 error = fget_unlocked(fdp, fd, &cap_flock_rights, &fp, NULL((void *)0));
726 if (error != 0)
727 break;
728 if (fp->f_type != DTYPE_VNODE1) {
729 error = EBADF9;
730 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
731 break;
732 }
733 flp = (struct flock *)arg;
734 if (flp->l_type != F_RDLCK1 && flp->l_type != F_WRLCK3 &&
735 flp->l_type != F_UNLCK2) {
736 error = EINVAL22;
737 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
738 break;
739 }
740 if (flp->l_whence == SEEK_CUR1) {
741 foffset = foffset_get(fp);
742 if ((flp->l_start > 0 &&
743 foffset > OFF_MAX0x7fffffffffffffff - flp->l_start) ||
744 (flp->l_start < 0 &&
745 foffset < OFF_MIN(-0x7fffffffffffffff - 1) - flp->l_start)) {
746 error = EOVERFLOW84;
747 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
748 break;
749 }
750 flp->l_start += foffset;
751 }
752 vp = fp->f_vnode;
753 error = VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_GETLK11, flp,
754 F_POSIX0x040);
755 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
756 break;
757
758 case F_RDAHEAD16:
759 arg = arg ? 128 * 1024: 0;
760 /* FALLTHROUGH */
761 case F_READAHEAD15:
762 error = fget_unlocked(fdp, fd, &cap_no_rights, &fp, NULL((void *)0));
763 if (error != 0)
764 break;
765 if (fp->f_type != DTYPE_VNODE1) {
766 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
767 error = EBADF9;
768 break;
769 }
770 vp = fp->f_vnode;
771 /*
772 * Exclusive lock synchronizes against f_seqcount reads and
773 * writes in sequential_heuristic().
774 */
775 error = vn_lock(vp, LK_EXCLUSIVE)_vn_lock(vp, 0x080000, "/root/freebsd/sys/kern/kern_descrip.c"
, 775)
;
776 if (error != 0) {
777 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
778 break;
779 }
780 if (arg >= 0) {
781 bsize = fp->f_vnode->v_mount->mnt_stat.f_iosize;
782 fp->f_seqcount = (arg + bsize - 1) / bsize;
783 atomic_set_int(&fp->f_flag, FRDAHEAD0x0200);
784 } else {
785 atomic_clear_int(&fp->f_flag, FRDAHEAD0x0200);
786 }
787 VOP_UNLOCK(vp, 0);
788 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
789 break;
790
791 default:
792 error = EINVAL22;
793 break;
794 }
795 return (error);
796}
797
798static int
799getmaxfd(struct thread *td)
800{
801
802 return (min((int)lim_cur(td, RLIMIT_NOFILE)({ rlim_t _rlim; struct thread *_td = (td); int _which = (8);
if (__builtin_constant_p(8) && 8 != 2 && 8 !=
3 && 8 != 10) { _rlim = td->td_limit->pl_rlimit
[8].rlim_cur; } else { _rlim = lim_cur(_td, _which); } _rlim;
})
, maxfilesperproc));
803}
804
805/*
806 * Common code for dup, dup2, fcntl(F_DUPFD) and fcntl(F_DUP2FD).
807 */
808int
809kern_dup(struct thread *td, u_int mode, int flags, int old, int new)
810{
811 struct filedesc *fdp;
812 struct filedescent *oldfde, *newfde;
813 struct proc *p;
814 struct file *delfp;
815 u_long *oioctls, *nioctls;
816 int error, maxfd;
817
818 p = td->td_proc;
819 fdp = p->p_fd;
820 oioctls = NULL((void *)0);
821
822 MPASS((flags & ~(FDDUP_FLAG_CLOEXEC)) == 0)do { if (__builtin_expect((!(((flags & ~(0x1)) == 0))), 0
)) panic ("Assertion %s failed at %s:%d", "(flags & ~(FDDUP_FLAG_CLOEXEC)) == 0"
, "/root/freebsd/sys/kern/kern_descrip.c", 822); } while (0)
;
823 MPASS(mode < FDDUP_LASTMODE)do { if (__builtin_expect((!((mode < FDDUP_LASTMODE))), 0)
) panic ("Assertion %s failed at %s:%d", "mode < FDDUP_LASTMODE"
, "/root/freebsd/sys/kern/kern_descrip.c", 823); } while (0)
;
824
825 AUDIT_ARG_FD(old)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fd((old)); } while (0)
;
826 /* XXXRW: if (flags & FDDUP_FIXED) AUDIT_ARG_FD2(new); */
827
828 /*
829 * Verify we have a valid descriptor to dup from and possibly to
830 * dup to. Unlike dup() and dup2(), fcntl()'s F_DUPFD should
831 * return EINVAL when the new descriptor is out of bounds.
832 */
833 if (old < 0)
834 return (EBADF9);
835 if (new < 0)
836 return (mode == FDDUP_FCNTL ? EINVAL22 : EBADF9);
837 maxfd = getmaxfd(td);
838 if (new >= maxfd)
839 return (mode == FDDUP_FCNTL ? EINVAL22 : EBADF9);
840
841 error = EBADF9;
842 FILEDESC_XLOCK(fdp)(void)_sx_xlock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (842))
;
843 if (fget_locked(fdp, old) == NULL((void *)0))
844 goto unlock;
845 if ((mode == FDDUP_FIXED || mode == FDDUP_MUSTREPLACE) && old == new) {
846 td->td_retvaltd_uretoff.tdu_retval[0] = new;
847 if (flags & FDDUP_FLAG_CLOEXEC0x1)
848 fdp->fd_ofilesfd_files->fdt_ofiles[new].fde_flags |= UF_EXCLOSE0x01;
849 error = 0;
850 goto unlock;
851 }
852
853 /*
854 * If the caller specified a file descriptor, make sure the file
855 * table is large enough to hold it, and grab it. Otherwise, just
856 * allocate a new descriptor the usual way.
857 */
858 switch (mode) {
859 case FDDUP_NORMAL:
860 case FDDUP_FCNTL:
861 if ((error = fdalloc(td, new, &new)) != 0)
862 goto unlock;
863 break;
864 case FDDUP_MUSTREPLACE:
865 /* Target file descriptor must exist. */
866 if (fget_locked(fdp, new) == NULL((void *)0))
867 goto unlock;
868 break;
869 case FDDUP_FIXED:
870 if (new >= fdp->fd_nfilesfd_files->fdt_nfiles) {
871 /*
872 * The resource limits are here instead of e.g.
873 * fdalloc(), because the file descriptor table may be
874 * shared between processes, so we can't really use
875 * racct_add()/racct_sub(). Instead of counting the
876 * number of actually allocated descriptors, just put
877 * the limit on the size of the file descriptor table.
878 */
879#ifdef RACCT1
880 if (RACCT_ENABLED()__builtin_expect((racct_enable), 0)) {
881 error = racct_set_unlocked(p, RACCT_NOFILE7, new + 1);
882 if (error != 0) {
883 error = EMFILE24;
884 goto unlock;
885 }
886 }
887#endif
888 fdgrowtable_exp(fdp, new + 1);
889 }
890 if (!fdisused(fdp, new))
891 fdused(fdp, new);
892 break;
893 default:
894 KASSERT(0, ("%s unsupported mode %d", __func__, mode))do { if (__builtin_expect((!(0)), 0)) panic ("%s unsupported mode %d"
, __func__, mode); } while (0)
;
895 }
896
897 KASSERT(old != new, ("new fd is same as old"))do { if (__builtin_expect((!(old != new)), 0)) panic ("new fd is same as old"
); } while (0)
;
898
899 oldfde = &fdp->fd_ofilesfd_files->fdt_ofiles[old];
900 fhold(oldfde->fde_file)(refcount_acquire(&(oldfde->fde_file)->f_count));
901 newfde = &fdp->fd_ofilesfd_files->fdt_ofiles[new];
902 delfp = newfde->fde_file;
903
904 oioctls = filecaps_free_prep(&newfde->fde_caps);
905 nioctls = filecaps_copy_prep(&oldfde->fde_caps);
906
907 /*
908 * Duplicate the source descriptor.
909 */
910#ifdef CAPABILITIES1
911 seq_write_begin(&newfde->fde_seq);
912#endif
913 memcpy(newfde, oldfde, fde_change_size)__builtin_memcpy((newfde), (oldfde), ((__builtin_offsetof(struct
filedescent, fde_seq))))
;
914 filecaps_copy_finish(&oldfde->fde_caps, &newfde->fde_caps,
915 nioctls);
916 if ((flags & FDDUP_FLAG_CLOEXEC0x1) != 0)
917 newfde->fde_flags = oldfde->fde_flags | UF_EXCLOSE0x01;
918 else
919 newfde->fde_flags = oldfde->fde_flags & ~UF_EXCLOSE0x01;
920#ifdef CAPABILITIES1
921 seq_write_end(&newfde->fde_seq);
922#endif
923 td->td_retvaltd_uretoff.tdu_retval[0] = new;
924
925 error = 0;
926
927 if (delfp != NULL((void *)0)) {
928 (void) closefp(fdp, new, delfp, td, 1);
929 FILEDESC_UNLOCK_ASSERT(fdp)_sx_assert(((&(fdp)->fd_sx)), ((0x00000000)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (929))
;
930 } else {
931unlock:
932 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (932))
;
933 }
934
935 filecaps_free_finish(oioctls);
936 return (error);
937}
938
939/*
940 * If sigio is on the list associated with a process or process group,
941 * disable signalling from the device, remove sigio from the list and
942 * free sigio.
943 */
944void
945funsetown(struct sigio **sigiop)
946{
947 struct sigio *sigio;
948
949 if (*sigiop == NULL((void *)0))
950 return;
951 SIGIO_LOCK()__mtx_lock_flags(&((((&sigio_lock))))->mtx_lock, (
(0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (951))
;
952 sigio = *sigiop;
953 if (sigio == NULL((void *)0)) {
954 SIGIO_UNLOCK()__mtx_unlock_flags(&((((&sigio_lock))))->mtx_lock,
((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (954))
;
955 return;
956 }
957 *(sigio->sio_myref) = NULL((void *)0);
958 if ((sigio)->sio_pgid < 0) {
959 struct pgrp *pg = (sigio)->sio_pgrpsio_u.siu_pgrp;
960 PGRP_LOCK(pg)__mtx_lock_flags(&((((&(pg)->pg_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (960))
;
961 SLIST_REMOVE(&sigio->sio_pgrp->pg_sigiolst, sigio,do { ; if ((((&sigio->sio_u.siu_pgrp->pg_sigiolst))
->slh_first) == (sigio)) { do { ((((&sigio->sio_u.siu_pgrp
->pg_sigiolst)))->slh_first) = ((((((&sigio->sio_u
.siu_pgrp->pg_sigiolst)))->slh_first))->sio_pgsigio.
sle_next); } while (0); } else { struct sigio *curelm = ((&
sigio->sio_u.siu_pgrp->pg_sigiolst)->slh_first); while
(((curelm)->sio_pgsigio.sle_next) != (sigio)) curelm = ((
curelm)->sio_pgsigio.sle_next); do { ((curelm)->sio_pgsigio
.sle_next) = ((((curelm)->sio_pgsigio.sle_next))->sio_pgsigio
.sle_next); } while (0); } ; } while (0)
962 sigio, sio_pgsigio)do { ; if ((((&sigio->sio_u.siu_pgrp->pg_sigiolst))
->slh_first) == (sigio)) { do { ((((&sigio->sio_u.siu_pgrp
->pg_sigiolst)))->slh_first) = ((((((&sigio->sio_u
.siu_pgrp->pg_sigiolst)))->slh_first))->sio_pgsigio.
sle_next); } while (0); } else { struct sigio *curelm = ((&
sigio->sio_u.siu_pgrp->pg_sigiolst)->slh_first); while
(((curelm)->sio_pgsigio.sle_next) != (sigio)) curelm = ((
curelm)->sio_pgsigio.sle_next); do { ((curelm)->sio_pgsigio
.sle_next) = ((((curelm)->sio_pgsigio.sle_next))->sio_pgsigio
.sle_next); } while (0); } ; } while (0)
;
963 PGRP_UNLOCK(pg)__mtx_unlock_flags(&((((&(pg)->pg_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (963))
;
964 } else {
965 struct proc *p = (sigio)->sio_procsio_u.siu_proc;
966 PROC_LOCK(p)__mtx_lock_flags(&((((&(p)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (966))
;
967 SLIST_REMOVE(&sigio->sio_proc->p_sigiolst, sigio,do { ; if ((((&sigio->sio_u.siu_proc->p_sigiolst))->
slh_first) == (sigio)) { do { ((((&sigio->sio_u.siu_proc
->p_sigiolst)))->slh_first) = ((((((&sigio->sio_u
.siu_proc->p_sigiolst)))->slh_first))->sio_pgsigio.sle_next
); } while (0); } else { struct sigio *curelm = ((&sigio->
sio_u.siu_proc->p_sigiolst)->slh_first); while (((curelm
)->sio_pgsigio.sle_next) != (sigio)) curelm = ((curelm)->
sio_pgsigio.sle_next); do { ((curelm)->sio_pgsigio.sle_next
) = ((((curelm)->sio_pgsigio.sle_next))->sio_pgsigio.sle_next
); } while (0); } ; } while (0)
968 sigio, sio_pgsigio)do { ; if ((((&sigio->sio_u.siu_proc->p_sigiolst))->
slh_first) == (sigio)) { do { ((((&sigio->sio_u.siu_proc
->p_sigiolst)))->slh_first) = ((((((&sigio->sio_u
.siu_proc->p_sigiolst)))->slh_first))->sio_pgsigio.sle_next
); } while (0); } else { struct sigio *curelm = ((&sigio->
sio_u.siu_proc->p_sigiolst)->slh_first); while (((curelm
)->sio_pgsigio.sle_next) != (sigio)) curelm = ((curelm)->
sio_pgsigio.sle_next); do { ((curelm)->sio_pgsigio.sle_next
) = ((((curelm)->sio_pgsigio.sle_next))->sio_pgsigio.sle_next
); } while (0); } ; } while (0)
;
969 PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (969))
;
970 }
971 SIGIO_UNLOCK()__mtx_unlock_flags(&((((&sigio_lock))))->mtx_lock,
((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (971))
;
972 crfree(sigio->sio_ucred);
973 free(sigio, M_SIGIO);
974}
975
976/*
977 * Free a list of sigio structures.
978 * We only need to lock the SIGIO_LOCK because we have made ourselves
979 * inaccessible to callers of fsetown and therefore do not need to lock
980 * the proc or pgrp struct for the list manipulation.
981 */
982void
983funsetownlst(struct sigiolst *sigiolst)
984{
985 struct proc *p;
986 struct pgrp *pg;
987 struct sigio *sigio;
988
989 sigio = SLIST_FIRST(sigiolst)((sigiolst)->slh_first);
990 if (sigio == NULL((void *)0))
991 return;
992 p = NULL((void *)0);
993 pg = NULL((void *)0);
994
995 /*
996 * Every entry of the list should belong
997 * to a single proc or pgrp.
998 */
999 if (sigio->sio_pgid < 0) {
1000 pg = sigio->sio_pgrpsio_u.siu_pgrp;
1001 PGRP_LOCK_ASSERT(pg, MA_NOTOWNED)__mtx_assert(&(((&(pg)->pg_mtx)))->mtx_lock, ((
(0x00000000))), ("/root/freebsd/sys/kern/kern_descrip.c"), (1001
))
;
1002 } else /* if (sigio->sio_pgid > 0) */ {
1003 p = sigio->sio_procsio_u.siu_proc;
1004 PROC_LOCK_ASSERT(p, MA_NOTOWNED)__mtx_assert(&(((&(p)->p_mtx)))->mtx_lock, (((0x00000000
))), ("/root/freebsd/sys/kern/kern_descrip.c"), (1004))
;
1005 }
1006
1007 SIGIO_LOCK()__mtx_lock_flags(&((((&sigio_lock))))->mtx_lock, (
(0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1007))
;
1008 while ((sigio = SLIST_FIRST(sigiolst)((sigiolst)->slh_first)) != NULL((void *)0)) {
1009 *(sigio->sio_myref) = NULL((void *)0);
1010 if (pg != NULL((void *)0)) {
1011 KASSERT(sigio->sio_pgid < 0,do { if (__builtin_expect((!(sigio->sio_pgid < 0)), 0))
panic ("Proc sigio in pgrp sigio list"); } while (0)
1012 ("Proc sigio in pgrp sigio list"))do { if (__builtin_expect((!(sigio->sio_pgid < 0)), 0))
panic ("Proc sigio in pgrp sigio list"); } while (0)
;
1013 KASSERT(sigio->sio_pgrp == pg,do { if (__builtin_expect((!(sigio->sio_u.siu_pgrp == pg))
, 0)) panic ("Bogus pgrp in sigio list"); } while (0)
1014 ("Bogus pgrp in sigio list"))do { if (__builtin_expect((!(sigio->sio_u.siu_pgrp == pg))
, 0)) panic ("Bogus pgrp in sigio list"); } while (0)
;
1015 PGRP_LOCK(pg)__mtx_lock_flags(&((((&(pg)->pg_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1015))
;
1016 SLIST_REMOVE(&pg->pg_sigiolst, sigio, sigio,do { ; if ((((&pg->pg_sigiolst))->slh_first) == (sigio
)) { do { ((((&pg->pg_sigiolst)))->slh_first) = (((
(((&pg->pg_sigiolst)))->slh_first))->sio_pgsigio
.sle_next); } while (0); } else { struct sigio *curelm = ((&
pg->pg_sigiolst)->slh_first); while (((curelm)->sio_pgsigio
.sle_next) != (sigio)) curelm = ((curelm)->sio_pgsigio.sle_next
); do { ((curelm)->sio_pgsigio.sle_next) = ((((curelm)->
sio_pgsigio.sle_next))->sio_pgsigio.sle_next); } while (0)
; } ; } while (0)
1017 sio_pgsigio)do { ; if ((((&pg->pg_sigiolst))->slh_first) == (sigio
)) { do { ((((&pg->pg_sigiolst)))->slh_first) = (((
(((&pg->pg_sigiolst)))->slh_first))->sio_pgsigio
.sle_next); } while (0); } else { struct sigio *curelm = ((&
pg->pg_sigiolst)->slh_first); while (((curelm)->sio_pgsigio
.sle_next) != (sigio)) curelm = ((curelm)->sio_pgsigio.sle_next
); do { ((curelm)->sio_pgsigio.sle_next) = ((((curelm)->
sio_pgsigio.sle_next))->sio_pgsigio.sle_next); } while (0)
; } ; } while (0)
;
1018 PGRP_UNLOCK(pg)__mtx_unlock_flags(&((((&(pg)->pg_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1018))
;
1019 } else /* if (p != NULL) */ {
1020 KASSERT(sigio->sio_pgid > 0,do { if (__builtin_expect((!(sigio->sio_pgid > 0)), 0))
panic ("Pgrp sigio in proc sigio list"); } while (0)
1021 ("Pgrp sigio in proc sigio list"))do { if (__builtin_expect((!(sigio->sio_pgid > 0)), 0))
panic ("Pgrp sigio in proc sigio list"); } while (0)
;
1022 KASSERT(sigio->sio_proc == p,do { if (__builtin_expect((!(sigio->sio_u.siu_proc == p)),
0)) panic ("Bogus proc in sigio list"); } while (0)
1023 ("Bogus proc in sigio list"))do { if (__builtin_expect((!(sigio->sio_u.siu_proc == p)),
0)) panic ("Bogus proc in sigio list"); } while (0)
;
1024 PROC_LOCK(p)__mtx_lock_flags(&((((&(p)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1024))
;
1025 SLIST_REMOVE(&p->p_sigiolst, sigio, sigio,do { ; if ((((&p->p_sigiolst))->slh_first) == (sigio
)) { do { ((((&p->p_sigiolst)))->slh_first) = (((((
(&p->p_sigiolst)))->slh_first))->sio_pgsigio.sle_next
); } while (0); } else { struct sigio *curelm = ((&p->
p_sigiolst)->slh_first); while (((curelm)->sio_pgsigio.
sle_next) != (sigio)) curelm = ((curelm)->sio_pgsigio.sle_next
); do { ((curelm)->sio_pgsigio.sle_next) = ((((curelm)->
sio_pgsigio.sle_next))->sio_pgsigio.sle_next); } while (0)
; } ; } while (0)
1026 sio_pgsigio)do { ; if ((((&p->p_sigiolst))->slh_first) == (sigio
)) { do { ((((&p->p_sigiolst)))->slh_first) = (((((
(&p->p_sigiolst)))->slh_first))->sio_pgsigio.sle_next
); } while (0); } else { struct sigio *curelm = ((&p->
p_sigiolst)->slh_first); while (((curelm)->sio_pgsigio.
sle_next) != (sigio)) curelm = ((curelm)->sio_pgsigio.sle_next
); do { ((curelm)->sio_pgsigio.sle_next) = ((((curelm)->
sio_pgsigio.sle_next))->sio_pgsigio.sle_next); } while (0)
; } ; } while (0)
;
1027 PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1027))
;
1028 }
1029 SIGIO_UNLOCK()__mtx_unlock_flags(&((((&sigio_lock))))->mtx_lock,
((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1029))
;
1030 crfree(sigio->sio_ucred);
1031 free(sigio, M_SIGIO);
1032 SIGIO_LOCK()__mtx_lock_flags(&((((&sigio_lock))))->mtx_lock, (
(0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1032))
;
1033 }
1034 SIGIO_UNLOCK()__mtx_unlock_flags(&((((&sigio_lock))))->mtx_lock,
((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1034))
;
1035}
1036
1037/*
1038 * This is common code for FIOSETOWN ioctl called by fcntl(fd, F_SETOWN, arg).
1039 *
1040 * After permission checking, add a sigio structure to the sigio list for
1041 * the process or process group.
1042 */
1043int
1044fsetown(pid_t pgid, struct sigio **sigiop)
1045{
1046 struct proc *proc;
1047 struct pgrp *pgrp;
1048 struct sigio *sigio;
1049 int ret;
1050
1051 if (pgid == 0) {
1052 funsetown(sigiop);
1053 return (0);
1054 }
1055
1056 ret = 0;
1057
1058 /* Allocate and fill in the new sigio out of locks. */
1059 sigio = malloc(sizeof(struct sigio), M_SIGIO, M_WAITOK0x0002);
1060 sigio->sio_pgid = pgid;
1061 sigio->sio_ucred = crhold(curthread(__curthread())->td_ucred);
1062 sigio->sio_myref = sigiop;
1063
1064 sx_slock(&proctree_lock)(void)_sx_slock(((&proctree_lock)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (1064))
;
1065 if (pgid > 0) {
1066 proc = pfind(pgid);
1067 if (proc == NULL((void *)0)) {
1068 ret = ESRCH3;
1069 goto fail;
1070 }
1071
1072 /*
1073 * Policy - Don't allow a process to FSETOWN a process
1074 * in another session.
1075 *
1076 * Remove this test to allow maximum flexibility or
1077 * restrict FSETOWN to the current process or process
1078 * group for maximum safety.
1079 */
1080 PROC_UNLOCK(proc)__mtx_unlock_flags(&((((&(proc)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1080))
;
1081 if (proc->p_sessionp_pgrp->pg_session != curthread(__curthread())->td_proc->p_sessionp_pgrp->pg_session) {
1082 ret = EPERM1;
1083 goto fail;
1084 }
1085
1086 pgrp = NULL((void *)0);
1087 } else /* if (pgid < 0) */ {
1088 pgrp = pgfind(-pgid);
1089 if (pgrp == NULL((void *)0)) {
1090 ret = ESRCH3;
1091 goto fail;
1092 }
1093 PGRP_UNLOCK(pgrp)__mtx_unlock_flags(&((((&(pgrp)->pg_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1093))
;
1094
1095 /*
1096 * Policy - Don't allow a process to FSETOWN a process
1097 * in another session.
1098 *
1099 * Remove this test to allow maximum flexibility or
1100 * restrict FSETOWN to the current process or process
1101 * group for maximum safety.
1102 */
1103 if (pgrp->pg_session != curthread(__curthread())->td_proc->p_sessionp_pgrp->pg_session) {
1104 ret = EPERM1;
1105 goto fail;
1106 }
1107
1108 proc = NULL((void *)0);
1109 }
1110 funsetown(sigiop);
1111 if (pgid > 0) {
1112 PROC_LOCK(proc)__mtx_lock_flags(&((((&(proc)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1112))
;
1113 /*
1114 * Since funsetownlst() is called without the proctree
1115 * locked, we need to check for P_WEXIT.
1116 * XXX: is ESRCH correct?
1117 */
1118 if ((proc->p_flag & P_WEXIT0x02000) != 0) {
1119 PROC_UNLOCK(proc)__mtx_unlock_flags(&((((&(proc)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1119))
;
1120 ret = ESRCH3;
1121 goto fail;
1122 }
1123 SLIST_INSERT_HEAD(&proc->p_sigiolst, sigio, sio_pgsigio)do { (((sigio))->sio_pgsigio.sle_next) = (((&proc->
p_sigiolst))->slh_first); (((&proc->p_sigiolst))->
slh_first) = (sigio); } while (0)
;
1124 sigio->sio_procsio_u.siu_proc = proc;
1125 PROC_UNLOCK(proc)__mtx_unlock_flags(&((((&(proc)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1125))
;
1126 } else {
1127 PGRP_LOCK(pgrp)__mtx_lock_flags(&((((&(pgrp)->pg_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1127))
;
1128 SLIST_INSERT_HEAD(&pgrp->pg_sigiolst, sigio, sio_pgsigio)do { (((sigio))->sio_pgsigio.sle_next) = (((&pgrp->
pg_sigiolst))->slh_first); (((&pgrp->pg_sigiolst))->
slh_first) = (sigio); } while (0)
;
1129 sigio->sio_pgrpsio_u.siu_pgrp = pgrp;
1130 PGRP_UNLOCK(pgrp)__mtx_unlock_flags(&((((&(pgrp)->pg_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1130))
;
1131 }
1132 sx_sunlock(&proctree_lock)_sx_sunlock(((&proctree_lock)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (1132))
;
1133 SIGIO_LOCK()__mtx_lock_flags(&((((&sigio_lock))))->mtx_lock, (
(0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1133))
;
1134 *sigiop = sigio;
1135 SIGIO_UNLOCK()__mtx_unlock_flags(&((((&sigio_lock))))->mtx_lock,
((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1135))
;
1136 return (0);
1137
1138fail:
1139 sx_sunlock(&proctree_lock)_sx_sunlock(((&proctree_lock)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (1139))
;
1140 crfree(sigio->sio_ucred);
1141 free(sigio, M_SIGIO);
1142 return (ret);
1143}
1144
1145/*
1146 * This is common code for FIOGETOWN ioctl called by fcntl(fd, F_GETOWN, arg).
1147 */
1148pid_t
1149fgetown(struct sigio **sigiop)
1150{
1151 pid_t pgid;
1152
1153 SIGIO_LOCK()__mtx_lock_flags(&((((&sigio_lock))))->mtx_lock, (
(0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1153))
;
1154 pgid = (*sigiop != NULL((void *)0)) ? (*sigiop)->sio_pgid : 0;
1155 SIGIO_UNLOCK()__mtx_unlock_flags(&((((&sigio_lock))))->mtx_lock,
((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1155))
;
1156 return (pgid);
1157}
1158
1159/*
1160 * Function drops the filedesc lock on return.
1161 */
1162static int
1163closefp(struct filedesc *fdp, int fd, struct file *fp, struct thread *td,
1164 int holdleaders)
1165{
1166 int error;
1167
1168 FILEDESC_XLOCK_ASSERT(fdp)_sx_assert(((&(fdp)->fd_sx)), ((0x00000004 | 0x00000010
)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1168))
;
1169
1170 if (holdleaders) {
1171 if (td->td_proc->p_fdtol != NULL((void *)0)) {
1172 /*
1173 * Ask fdfree() to sleep to ensure that all relevant
1174 * process leaders can be traversed in closef().
1175 */
1176 fdp->fd_holdleaderscount++;
1177 } else {
1178 holdleaders = 0;
1179 }
1180 }
1181
1182 /*
1183 * We now hold the fp reference that used to be owned by the
1184 * descriptor array. We have to unlock the FILEDESC *AFTER*
1185 * knote_fdclose to prevent a race of the fd getting opened, a knote
1186 * added, and deleteing a knote for the new fd.
1187 */
1188 if (__predict_false(!TAILQ_EMPTY(&fdp->fd_kqlist))__builtin_expect((!((&fdp->fd_kqlist)->tqh_first ==
((void *)0))), 0)
)
1189 knote_fdclose(td, fd);
1190
1191 /*
1192 * We need to notify mqueue if the object is of type mqueue.
1193 */
1194 if (__predict_false(fp->f_type == DTYPE_MQUEUE)__builtin_expect((fp->f_type == 7), 0))
1195 mq_fdclose(td, fd, fp);
1196 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (1196))
;
1197
1198 error = closef(fp, td);
1199 if (holdleaders) {
1200 FILEDESC_XLOCK(fdp)(void)_sx_xlock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (1200))
;
1201 fdp->fd_holdleaderscount--;
1202 if (fdp->fd_holdleaderscount == 0 &&
1203 fdp->fd_holdleaderswakeup != 0) {
1204 fdp->fd_holdleaderswakeup = 0;
1205 wakeup(&fdp->fd_holdleaderscount);
1206 }
1207 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (1207))
;
1208 }
1209 return (error);
1210}
1211
1212/*
1213 * Close a file descriptor.
1214 */
1215#ifndef _SYS_SYSPROTO_H_
1216struct close_args {
1217 int fd;
1218};
1219#endif
1220/* ARGSUSED */
1221int
1222sys_close(struct thread *td, struct close_args *uap)
1223{
1224
1225 return (kern_close(td, uap->fd));
1226}
1227
1228int
1229kern_close(struct thread *td, int fd)
1230{
1231 struct filedesc *fdp;
1232 struct file *fp;
1233
1234 fdp = td->td_proc->p_fd;
1235
1236 AUDIT_SYSCLOSE(td, fd)do { if ((__builtin_expect(((td)->td_pflags & 0x01000000
), 0))) audit_sysclose(td, fd); } while (0)
;
1237
1238 FILEDESC_XLOCK(fdp)(void)_sx_xlock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (1238))
;
1239 if ((fp = fget_locked(fdp, fd)) == NULL((void *)0)) {
1240 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (1240))
;
1241 return (EBADF9);
1242 }
1243 fdfree(fdp, fd);
1244
1245 /* closefp() drops the FILEDESC lock for us. */
1246 return (closefp(fdp, fd, fp, td, 1));
1247}
1248
1249/*
1250 * Close open file descriptors.
1251 */
1252#ifndef _SYS_SYSPROTO_H_
1253struct closefrom_args {
1254 int lowfd;
1255};
1256#endif
1257/* ARGSUSED */
1258int
1259sys_closefrom(struct thread *td, struct closefrom_args *uap)
1260{
1261 struct filedesc *fdp;
1262 int fd;
1263
1264 fdp = td->td_proc->p_fd;
1265 AUDIT_ARG_FD(uap->lowfd)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fd((uap->lowfd)); } while (0)
;
1266
1267 /*
1268 * Treat negative starting file descriptor values identical to
1269 * closefrom(0) which closes all files.
1270 */
1271 if (uap->lowfd < 0)
1272 uap->lowfd = 0;
1273 FILEDESC_SLOCK(fdp)(void)_sx_slock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (1273))
;
1274 for (fd = uap->lowfd; fd <= fdp->fd_lastfile; fd++) {
1275 if (fdp->fd_ofilesfd_files->fdt_ofiles[fd].fde_file != NULL((void *)0)) {
1276 FILEDESC_SUNLOCK(fdp)_sx_sunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (1276))
;
1277 (void)kern_close(td, fd);
1278 FILEDESC_SLOCK(fdp)(void)_sx_slock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (1278))
;
1279 }
1280 }
1281 FILEDESC_SUNLOCK(fdp)_sx_sunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (1281))
;
1282 return (0);
1283}
1284
1285#if defined(COMPAT_43)
1286/*
1287 * Return status information about a file descriptor.
1288 */
1289#ifndef _SYS_SYSPROTO_H_
1290struct ofstat_args {
1291 int fd;
1292 struct ostat *sb;
1293};
1294#endif
1295/* ARGSUSED */
1296int
1297ofstat(struct thread *td, struct ofstat_args *uap)
1298{
1299 struct ostat oub;
1300 struct stat ub;
1301 int error;
1302
1303 error = kern_fstat(td, uap->fd, &ub);
1304 if (error == 0) {
1305 cvtstat(&ub, &oub);
1306 error = copyout(&oub, uap->sb, sizeof(oub));
1307 }
1308 return (error);
1309}
1310#endif /* COMPAT_43 */
1311
1312#if defined(COMPAT_FREEBSD111)
1313int
1314freebsd11_fstat(struct thread *td, struct freebsd11_fstat_args *uap)
1315{
1316 struct stat sb;
1317 struct freebsd11_stat osb;
1318 int error;
1319
1320 error = kern_fstat(td, uap->fd, &sb);
1321 if (error != 0)
1322 return (error);
1323 error = freebsd11_cvtstat(&sb, &osb);
1324 if (error == 0)
1325 error = copyout(&osb, uap->sb, sizeof(osb));
1326 return (error);
1327}
1328#endif /* COMPAT_FREEBSD11 */
1329
1330/*
1331 * Return status information about a file descriptor.
1332 */
1333#ifndef _SYS_SYSPROTO_H_
1334struct fstat_args {
1335 int fd;
1336 struct stat *sb;
1337};
1338#endif
1339/* ARGSUSED */
1340int
1341sys_fstat(struct thread *td, struct fstat_args *uap)
1342{
1343 struct stat ub;
1344 int error;
1345
1346 error = kern_fstat(td, uap->fd, &ub);
1347 if (error == 0)
1348 error = copyout(&ub, uap->sb, sizeof(ub));
1349 return (error);
1350}
1351
1352int
1353kern_fstat(struct thread *td, int fd, struct stat *sbp)
1354{
1355 struct file *fp;
1356 int error;
1357
1358 AUDIT_ARG_FD(fd)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fd((fd)); } while (0)
;
1359
1360 error = fget(td, fd, &cap_fstat_rights, &fp);
1361 if (error != 0)
1362 return (error);
1363
1364 AUDIT_ARG_FILE(td->td_proc, fp)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_file((td->td_proc), (fp)); } while
(0)
;
1365
1366 error = fo_stat(fp, sbp, td->td_ucred, td);
1367 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
1368#ifdef __STAT_TIME_T_EXT
1369 if (error == 0) {
1370 sbp->st_atim_ext = 0;
1371 sbp->st_mtim_ext = 0;
1372 sbp->st_ctim_ext = 0;
1373 sbp->st_btim_ext = 0;
1374 }
1375#endif
1376#ifdef KTRACE1
1377 if (error == 0 && KTRPOINT(td, KTR_STRUCT)(__builtin_expect(((((td))->td_proc->p_traceflag & (
1 << (8)))), 0))
)
1378 ktrstat(sbp)ktrstruct("stat", (sbp), sizeof(struct stat));
1379#endif
1380 return (error);
1381}
1382
1383#if defined(COMPAT_FREEBSD111)
1384/*
1385 * Return status information about a file descriptor.
1386 */
1387#ifndef _SYS_SYSPROTO_H_
1388struct freebsd11_nfstat_args {
1389 int fd;
1390 struct nstat *sb;
1391};
1392#endif
1393/* ARGSUSED */
1394int
1395freebsd11_nfstat(struct thread *td, struct freebsd11_nfstat_args *uap)
1396{
1397 struct nstat nub;
1398 struct stat ub;
1399 int error;
1400
1401 error = kern_fstat(td, uap->fd, &ub);
1402 if (error == 0) {
1
Taking true branch
1403 freebsd11_cvtnstat(&ub, &nub);
1404 error = copyout(&nub, uap->sb, sizeof(nub));
2
Copies out a struct with uncleared padding (>= 4 bytes)
1405 }
1406 return (error);
1407}
1408#endif /* COMPAT_FREEBSD11 */
1409
1410/*
1411 * Return pathconf information about a file descriptor.
1412 */
1413#ifndef _SYS_SYSPROTO_H_
1414struct fpathconf_args {
1415 int fd;
1416 int name;
1417};
1418#endif
1419/* ARGSUSED */
1420int
1421sys_fpathconf(struct thread *td, struct fpathconf_args *uap)
1422{
1423 long value;
1424 int error;
1425
1426 error = kern_fpathconf(td, uap->fd, uap->name, &value);
1427 if (error == 0)
1428 td->td_retvaltd_uretoff.tdu_retval[0] = value;
1429 return (error);
1430}
1431
1432int
1433kern_fpathconf(struct thread *td, int fd, int name, long *valuep)
1434{
1435 struct file *fp;
1436 struct vnode *vp;
1437 int error;
1438
1439 error = fget(td, fd, &cap_fpathconf_rights, &fp);
1440 if (error != 0)
1441 return (error);
1442
1443 if (name == _PC_ASYNC_IO53) {
1444 *valuep = _POSIX_ASYNCHRONOUS_IO200112L;
1445 goto out;
1446 }
1447 vp = fp->f_vnode;
1448 if (vp != NULL((void *)0)) {
1449 vn_lock(vp, LK_SHARED | LK_RETRY)_vn_lock(vp, 0x200000 | 0x000400, "/root/freebsd/sys/kern/kern_descrip.c"
, 1449)
;
1450 error = VOP_PATHCONF(vp, name, valuep);
1451 VOP_UNLOCK(vp, 0);
1452 } else if (fp->f_type == DTYPE_PIPE3 || fp->f_type == DTYPE_SOCKET2) {
1453 if (name != _PC_PIPE_BUF6) {
1454 error = EINVAL22;
1455 } else {
1456 *valuep = PIPE_BUF512;
1457 error = 0;
1458 }
1459 } else {
1460 error = EOPNOTSUPP45;
1461 }
1462out:
1463 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
1464 return (error);
1465}
1466
1467/*
1468 * Copy filecaps structure allocating memory for ioctls array if needed.
1469 *
1470 * The last parameter indicates whether the fdtable is locked. If it is not and
1471 * ioctls are encountered, copying fails and the caller must lock the table.
1472 *
1473 * Note that if the table was not locked, the caller has to check the relevant
1474 * sequence counter to determine whether the operation was successful.
1475 */
1476bool
1477filecaps_copy(const struct filecaps *src, struct filecaps *dst, bool locked)
1478{
1479 size_t size;
1480
1481 if (src->fc_ioctls != NULL((void *)0) && !locked)
1482 return (false0);
1483 memcpy(dst, src, sizeof(*src))__builtin_memcpy((dst), (src), (sizeof(*src)));
1484 if (src->fc_ioctls == NULL((void *)0))
1485 return (true1);
1486
1487 KASSERT(src->fc_nioctls > 0,do { if (__builtin_expect((!(src->fc_nioctls > 0)), 0))
panic ("fc_ioctls != NULL, but fc_nioctls=%hd", src->fc_nioctls
); } while (0)
1488 ("fc_ioctls != NULL, but fc_nioctls=%hd", src->fc_nioctls))do { if (__builtin_expect((!(src->fc_nioctls > 0)), 0))
panic ("fc_ioctls != NULL, but fc_nioctls=%hd", src->fc_nioctls
); } while (0)
;
1489
1490 size = sizeof(src->fc_ioctls[0]) * src->fc_nioctls;
1491 dst->fc_ioctls = malloc(size, M_FILECAPS, M_WAITOK0x0002);
1492 memcpy(dst->fc_ioctls, src->fc_ioctls, size)__builtin_memcpy((dst->fc_ioctls), (src->fc_ioctls), (size
))
;
1493 return (true1);
1494}
1495
1496static u_long *
1497filecaps_copy_prep(const struct filecaps *src)
1498{
1499 u_long *ioctls;
1500 size_t size;
1501
1502 if (__predict_true(src->fc_ioctls == NULL)__builtin_expect((src->fc_ioctls == ((void *)0)), 1))
1503 return (NULL((void *)0));
1504
1505 KASSERT(src->fc_nioctls > 0,do { if (__builtin_expect((!(src->fc_nioctls > 0)), 0))
panic ("fc_ioctls != NULL, but fc_nioctls=%hd", src->fc_nioctls
); } while (0)
1506 ("fc_ioctls != NULL, but fc_nioctls=%hd", src->fc_nioctls))do { if (__builtin_expect((!(src->fc_nioctls > 0)), 0))
panic ("fc_ioctls != NULL, but fc_nioctls=%hd", src->fc_nioctls
); } while (0)
;
1507
1508 size = sizeof(src->fc_ioctls[0]) * src->fc_nioctls;
1509 ioctls = malloc(size, M_FILECAPS, M_WAITOK0x0002);
1510 return (ioctls);
1511}
1512
1513static void
1514filecaps_copy_finish(const struct filecaps *src, struct filecaps *dst,
1515 u_long *ioctls)
1516{
1517 size_t size;
1518
1519 *dst = *src;
1520 if (__predict_true(src->fc_ioctls == NULL)__builtin_expect((src->fc_ioctls == ((void *)0)), 1)) {
1521 MPASS(ioctls == NULL)do { if (__builtin_expect((!((ioctls == ((void *)0)))), 0)) panic
("Assertion %s failed at %s:%d", "ioctls == NULL", "/root/freebsd/sys/kern/kern_descrip.c"
, 1521); } while (0)
;
1522 return;
1523 }
1524
1525 size = sizeof(src->fc_ioctls[0]) * src->fc_nioctls;
1526 dst->fc_ioctls = ioctls;
1527 bcopy(src->fc_ioctls, dst->fc_ioctls, size)__builtin_memmove((dst->fc_ioctls), (src->fc_ioctls), (
size))
;
1528}
1529
1530/*
1531 * Move filecaps structure to the new place and clear the old place.
1532 */
1533void
1534filecaps_move(struct filecaps *src, struct filecaps *dst)
1535{
1536
1537 *dst = *src;
1538 bzero(src, sizeof(*src))__builtin_memset((src), 0, (sizeof(*src)));
1539}
1540
1541/*
1542 * Fill the given filecaps structure with full rights.
1543 */
1544static void
1545filecaps_fill(struct filecaps *fcaps)
1546{
1547
1548 CAP_ALL(&fcaps->fc_rights)do { (&fcaps->fc_rights)->cr_rights[0] = ((uint64_t
)0 << 62) | ((1ULL << (57 + (0))) | (0x000007FFFFFFFFFFULL
)); (&fcaps->fc_rights)->cr_rights[1] = ((1ULL <<
(57 + (1))) | (0x00000000001FFFFFULL)); } while (0)
;
1549 fcaps->fc_ioctls = NULL((void *)0);
1550 fcaps->fc_nioctls = -1;
1551 fcaps->fc_fcntls = CAP_FCNTL_ALL((1 << 3) | (1 << 4) | (1 << 5) | (1 <<
6))
;
1552}
1553
1554/*
1555 * Free memory allocated within filecaps structure.
1556 */
1557void
1558filecaps_free(struct filecaps *fcaps)
1559{
1560
1561 free(fcaps->fc_ioctls, M_FILECAPS);
1562 bzero(fcaps, sizeof(*fcaps))__builtin_memset((fcaps), 0, (sizeof(*fcaps)));
1563}
1564
1565static u_long *
1566filecaps_free_prep(struct filecaps *fcaps)
1567{
1568 u_long *ioctls;
1569
1570 ioctls = fcaps->fc_ioctls;
1571 bzero(fcaps, sizeof(*fcaps))__builtin_memset((fcaps), 0, (sizeof(*fcaps)));
1572 return (ioctls);
1573}
1574
1575static void
1576filecaps_free_finish(u_long *ioctls)
1577{
1578
1579 free(ioctls, M_FILECAPS);
1580}
1581
1582/*
1583 * Validate the given filecaps structure.
1584 */
1585static void
1586filecaps_validate(const struct filecaps *fcaps, const char *func)
1587{
1588
1589 KASSERT(cap_rights_is_valid(&fcaps->fc_rights),do { if (__builtin_expect((!(cap_rights_is_valid(&fcaps->
fc_rights))), 0)) panic ("%s: invalid rights", func); } while
(0)
1590 ("%s: invalid rights", func))do { if (__builtin_expect((!(cap_rights_is_valid(&fcaps->
fc_rights))), 0)) panic ("%s: invalid rights", func); } while
(0)
;
1591 KASSERT((fcaps->fc_fcntls & ~CAP_FCNTL_ALL) == 0,do { if (__builtin_expect((!((fcaps->fc_fcntls & ~((1 <<
3) | (1 << 4) | (1 << 5) | (1 << 6))) == 0
)), 0)) panic ("%s: invalid fcntls", func); } while (0)
1592 ("%s: invalid fcntls", func))do { if (__builtin_expect((!((fcaps->fc_fcntls & ~((1 <<
3) | (1 << 4) | (1 << 5) | (1 << 6))) == 0
)), 0)) panic ("%s: invalid fcntls", func); } while (0)
;
1593 KASSERT(fcaps->fc_fcntls == 0 ||do { if (__builtin_expect((!(fcaps->fc_fcntls == 0 || __cap_rights_is_set
(&fcaps->fc_rights, ((1ULL << (57 + (0))) | (0x0000000000008000ULL
)), 0ULL))), 0)) panic ("%s: fcntls without CAP_FCNTL", func)
; } while (0)
1594 cap_rights_is_set(&fcaps->fc_rights, CAP_FCNTL),do { if (__builtin_expect((!(fcaps->fc_fcntls == 0 || __cap_rights_is_set
(&fcaps->fc_rights, ((1ULL << (57 + (0))) | (0x0000000000008000ULL
)), 0ULL))), 0)) panic ("%s: fcntls without CAP_FCNTL", func)
; } while (0)
1595 ("%s: fcntls without CAP_FCNTL", func))do { if (__builtin_expect((!(fcaps->fc_fcntls == 0 || __cap_rights_is_set
(&fcaps->fc_rights, ((1ULL << (57 + (0))) | (0x0000000000008000ULL
)), 0ULL))), 0)) panic ("%s: fcntls without CAP_FCNTL", func)
; } while (0)
;
1596 KASSERT(fcaps->fc_ioctls != NULL ? fcaps->fc_nioctls > 0 :do { if (__builtin_expect((!(fcaps->fc_ioctls != ((void *)
0) ? fcaps->fc_nioctls > 0 : (fcaps->fc_nioctls == -
1 || fcaps->fc_nioctls == 0))), 0)) panic ("%s: invalid ioctls"
, func); } while (0)
1597 (fcaps->fc_nioctls == -1 || fcaps->fc_nioctls == 0),do { if (__builtin_expect((!(fcaps->fc_ioctls != ((void *)
0) ? fcaps->fc_nioctls > 0 : (fcaps->fc_nioctls == -
1 || fcaps->fc_nioctls == 0))), 0)) panic ("%s: invalid ioctls"
, func); } while (0)
1598 ("%s: invalid ioctls", func))do { if (__builtin_expect((!(fcaps->fc_ioctls != ((void *)
0) ? fcaps->fc_nioctls > 0 : (fcaps->fc_nioctls == -
1 || fcaps->fc_nioctls == 0))), 0)) panic ("%s: invalid ioctls"
, func); } while (0)
;
1599 KASSERT(fcaps->fc_nioctls == 0 ||do { if (__builtin_expect((!(fcaps->fc_nioctls == 0 || __cap_rights_is_set
(&fcaps->fc_rights, ((1ULL << (57 + (1))) | (0x0000000000000080ULL
)), 0ULL))), 0)) panic ("%s: ioctls without CAP_IOCTL", func)
; } while (0)
1600 cap_rights_is_set(&fcaps->fc_rights, CAP_IOCTL),do { if (__builtin_expect((!(fcaps->fc_nioctls == 0 || __cap_rights_is_set
(&fcaps->fc_rights, ((1ULL << (57 + (1))) | (0x0000000000000080ULL
)), 0ULL))), 0)) panic ("%s: ioctls without CAP_IOCTL", func)
; } while (0)
1601 ("%s: ioctls without CAP_IOCTL", func))do { if (__builtin_expect((!(fcaps->fc_nioctls == 0 || __cap_rights_is_set
(&fcaps->fc_rights, ((1ULL << (57 + (1))) | (0x0000000000000080ULL
)), 0ULL))), 0)) panic ("%s: ioctls without CAP_IOCTL", func)
; } while (0)
;
1602}
1603
1604static void
1605fdgrowtable_exp(struct filedesc *fdp, int nfd)
1606{
1607 int nfd1;
1608
1609 FILEDESC_XLOCK_ASSERT(fdp)_sx_assert(((&(fdp)->fd_sx)), ((0x00000004 | 0x00000010
)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1609))
;
1610
1611 nfd1 = fdp->fd_nfilesfd_files->fdt_nfiles * 2;
1612 if (nfd1 < nfd)
1613 nfd1 = nfd;
1614 fdgrowtable(fdp, nfd1);
1615}
1616
1617/*
1618 * Grow the file table to accommodate (at least) nfd descriptors.
1619 */
1620static void
1621fdgrowtable(struct filedesc *fdp, int nfd)
1622{
1623 struct filedesc0 *fdp0;
1624 struct freetable *ft;
1625 struct fdescenttbl *ntable;
1626 struct fdescenttbl *otable;
1627 int nnfiles, onfiles;
1628 NDSLOTTYPEu_long *nmap, *omap;
1629
1630 /*
1631 * If lastfile is -1 this struct filedesc was just allocated and we are
1632 * growing it to accommodate for the one we are going to copy from. There
1633 * is no need to have a lock on this one as it's not visible to anyone.
1634 */
1635 if (fdp->fd_lastfile != -1)
1636 FILEDESC_XLOCK_ASSERT(fdp)_sx_assert(((&(fdp)->fd_sx)), ((0x00000004 | 0x00000010
)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1636))
;
1637
1638 KASSERT(fdp->fd_nfiles > 0, ("zero-length file table"))do { if (__builtin_expect((!(fdp->fd_files->fdt_nfiles >
0)), 0)) panic ("zero-length file table"); } while (0)
;
1639
1640 /* save old values */
1641 onfiles = fdp->fd_nfilesfd_files->fdt_nfiles;
1642 otable = fdp->fd_files;
1643 omap = fdp->fd_map;
1644
1645 /* compute the size of the new table */
1646 nnfiles = NDSLOTS(nfd)(((nfd) + (sizeof(u_long) * 8) - 1) / (sizeof(u_long) * 8)) * NDENTRIES(sizeof(u_long) * 8); /* round up */
1647 if (nnfiles <= onfiles)
1648 /* the table is already large enough */
1649 return;
1650
1651 /*
1652 * Allocate a new table. We need enough space for the number of
1653 * entries, file entries themselves and the struct freetable we will use
1654 * when we decommission the table and place it on the freelist.
1655 * We place the struct freetable in the middle so we don't have
1656 * to worry about padding.
1657 */
1658 ntable = malloc(offsetof(struct fdescenttbl, fdt_ofiles)__builtin_offsetof(struct fdescenttbl, fdt_ofiles) +
1659 nnfiles * sizeof(ntable->fdt_ofiles[0]) +
1660 sizeof(struct freetable),
1661 M_FILEDESC, M_ZERO0x0100 | M_WAITOK0x0002);
1662 /* copy the old data */
1663 ntable->fdt_nfiles = nnfiles;
1664 memcpy(ntable->fdt_ofiles, otable->fdt_ofiles,__builtin_memcpy((ntable->fdt_ofiles), (otable->fdt_ofiles
), (onfiles * sizeof(ntable->fdt_ofiles[0])))
1665 onfiles * sizeof(ntable->fdt_ofiles[0]))__builtin_memcpy((ntable->fdt_ofiles), (otable->fdt_ofiles
), (onfiles * sizeof(ntable->fdt_ofiles[0])))
;
1666
1667 /*
1668 * Allocate a new map only if the old is not large enough. It will
1669 * grow at a slower rate than the table as it can map more
1670 * entries than the table can hold.
1671 */
1672 if (NDSLOTS(nnfiles)(((nnfiles) + (sizeof(u_long) * 8) - 1) / (sizeof(u_long) * 8
))
> NDSLOTS(onfiles)(((onfiles) + (sizeof(u_long) * 8) - 1) / (sizeof(u_long) * 8
))
) {
1673 nmap = malloc(NDSLOTS(nnfiles)(((nnfiles) + (sizeof(u_long) * 8) - 1) / (sizeof(u_long) * 8
))
* NDSLOTSIZEsizeof(u_long), M_FILEDESC,
1674 M_ZERO0x0100 | M_WAITOK0x0002);
1675 /* copy over the old data and update the pointer */
1676 memcpy(nmap, omap, NDSLOTS(onfiles) * sizeof(*omap))__builtin_memcpy((nmap), (omap), ((((onfiles) + (sizeof(u_long
) * 8) - 1) / (sizeof(u_long) * 8)) * sizeof(*omap)))
;
1677 fdp->fd_map = nmap;
1678 }
1679
1680 /*
1681 * Make sure that ntable is correctly initialized before we replace
1682 * fd_files poiner. Otherwise fget_unlocked() may see inconsistent
1683 * data.
1684 */
1685 atomic_store_rel_ptratomic_store_rel_long((volatile void *)&fdp->fd_files, (uintptr_t)ntable);
1686
1687 /*
1688 * Do not free the old file table, as some threads may still
1689 * reference entries within it. Instead, place it on a freelist
1690 * which will be processed when the struct filedesc is released.
1691 *
1692 * Note that if onfiles == NDFILE, we're dealing with the original
1693 * static allocation contained within (struct filedesc0 *)fdp,
1694 * which must not be freed.
1695 */
1696 if (onfiles > NDFILE20) {
1697 ft = (struct freetable *)&otable->fdt_ofiles[onfiles];
1698 fdp0 = (struct filedesc0 *)fdp;
1699 ft->ft_table = otable;
1700 SLIST_INSERT_HEAD(&fdp0->fd_free, ft, ft_next)do { (((ft))->ft_next.sle_next) = (((&fdp0->fd_free
))->slh_first); (((&fdp0->fd_free))->slh_first) =
(ft); } while (0)
;
1701 }
1702 /*
1703 * The map does not have the same possibility of threads still
1704 * holding references to it. So always free it as long as it
1705 * does not reference the original static allocation.
1706 */
1707 if (NDSLOTS(onfiles)(((onfiles) + (sizeof(u_long) * 8) - 1) / (sizeof(u_long) * 8
))
> NDSLOTS(NDFILE)(((20) + (sizeof(u_long) * 8) - 1) / (sizeof(u_long) * 8)))
1708 free(omap, M_FILEDESC);
1709}
1710
1711/*
1712 * Allocate a file descriptor for the process.
1713 */
1714int
1715fdalloc(struct thread *td, int minfd, int *result)
1716{
1717 struct proc *p = td->td_proc;
1718 struct filedesc *fdp = p->p_fd;
1719 int fd, maxfd, allocfd;
1720#ifdef RACCT1
1721 int error;
1722#endif
1723
1724 FILEDESC_XLOCK_ASSERT(fdp)_sx_assert(((&(fdp)->fd_sx)), ((0x00000004 | 0x00000010
)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1724))
;
1725
1726 if (fdp->fd_freefile > minfd)
1727 minfd = fdp->fd_freefile;
1728
1729 maxfd = getmaxfd(td);
1730
1731 /*
1732 * Search the bitmap for a free descriptor starting at minfd.
1733 * If none is found, grow the file table.
1734 */
1735 fd = fd_first_free(fdp, minfd, fdp->fd_nfilesfd_files->fdt_nfiles);
1736 if (fd >= maxfd)
1737 return (EMFILE24);
1738 if (fd >= fdp->fd_nfilesfd_files->fdt_nfiles) {
1739 allocfd = min(fd * 2, maxfd);
1740#ifdef RACCT1
1741 if (RACCT_ENABLED()__builtin_expect((racct_enable), 0)) {
1742 error = racct_set_unlocked(p, RACCT_NOFILE7, allocfd);
1743 if (error != 0)
1744 return (EMFILE24);
1745 }
1746#endif
1747 /*
1748 * fd is already equal to first free descriptor >= minfd, so
1749 * we only need to grow the table and we are done.
1750 */
1751 fdgrowtable_exp(fdp, allocfd);
1752 }
1753
1754 /*
1755 * Perform some sanity checks, then mark the file descriptor as
1756 * used and return it to the caller.
1757 */
1758 KASSERT(fd >= 0 && fd < min(maxfd, fdp->fd_nfiles),do { if (__builtin_expect((!(fd >= 0 && fd < min
(maxfd, fdp->fd_files->fdt_nfiles))), 0)) panic ("invalid descriptor %d"
, fd); } while (0)
1759 ("invalid descriptor %d", fd))do { if (__builtin_expect((!(fd >= 0 && fd < min
(maxfd, fdp->fd_files->fdt_nfiles))), 0)) panic ("invalid descriptor %d"
, fd); } while (0)
;
1760 KASSERT(!fdisused(fdp, fd),do { if (__builtin_expect((!(!fdisused(fdp, fd))), 0)) panic (
"fd_first_free() returned non-free descriptor"); } while (0)
1761 ("fd_first_free() returned non-free descriptor"))do { if (__builtin_expect((!(!fdisused(fdp, fd))), 0)) panic (
"fd_first_free() returned non-free descriptor"); } while (0)
;
1762 KASSERT(fdp->fd_ofiles[fd].fde_file == NULL,do { if (__builtin_expect((!(fdp->fd_files->fdt_ofiles[
fd].fde_file == ((void *)0))), 0)) panic ("file descriptor isn't free"
); } while (0)
1763 ("file descriptor isn't free"))do { if (__builtin_expect((!(fdp->fd_files->fdt_ofiles[
fd].fde_file == ((void *)0))), 0)) panic ("file descriptor isn't free"
); } while (0)
;
1764 fdused(fdp, fd);
1765 *result = fd;
1766 return (0);
1767}
1768
1769/*
1770 * Allocate n file descriptors for the process.
1771 */
1772int
1773fdallocn(struct thread *td, int minfd, int *fds, int n)
1774{
1775 struct proc *p = td->td_proc;
1776 struct filedesc *fdp = p->p_fd;
1777 int i;
1778
1779 FILEDESC_XLOCK_ASSERT(fdp)_sx_assert(((&(fdp)->fd_sx)), ((0x00000004 | 0x00000010
)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1779))
;
1780
1781 for (i = 0; i < n; i++)
1782 if (fdalloc(td, 0, &fds[i]) != 0)
1783 break;
1784
1785 if (i < n) {
1786 for (i--; i >= 0; i--)
1787 fdunused(fdp, fds[i]);
1788 return (EMFILE24);
1789 }
1790
1791 return (0);
1792}
1793
1794/*
1795 * Create a new open file structure and allocate a file descriptor for the
1796 * process that refers to it. We add one reference to the file for the
1797 * descriptor table and one reference for resultfp. This is to prevent us
1798 * being preempted and the entry in the descriptor table closed after we
1799 * release the FILEDESC lock.
1800 */
1801int
1802falloc_caps(struct thread *td, struct file **resultfp, int *resultfd, int flags,
1803 struct filecaps *fcaps)
1804{
1805 struct file *fp;
1806 int error, fd;
1807
1808 error = falloc_noinstall(td, &fp);
1809 if (error)
1810 return (error); /* no reference held on error */
1811
1812 error = finstall(td, fp, &fd, flags, fcaps);
1813 if (error) {
1814 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
; /* one reference (fp only) */
1815 return (error);
1816 }
1817
1818 if (resultfp != NULL((void *)0))
1819 *resultfp = fp; /* copy out result */
1820 else
1821 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
; /* release local reference */
1822
1823 if (resultfd != NULL((void *)0))
1824 *resultfd = fd;
1825
1826 return (0);
1827}
1828
1829/*
1830 * Create a new open file structure without allocating a file descriptor.
1831 */
1832int
1833falloc_noinstall(struct thread *td, struct file **resultfp)
1834{
1835 struct file *fp;
1836 int maxuserfiles = maxfiles - (maxfiles / 20);
1837 int openfiles_new;
1838 static struct timeval lastfail;
1839 static int curfail;
1840
1841 KASSERT(resultfp != NULL, ("%s: resultfp == NULL", __func__))do { if (__builtin_expect((!(resultfp != ((void *)0))), 0)) panic
("%s: resultfp == NULL", __func__); } while (0)
;
1842
1843 openfiles_new = atomic_fetchadd_int(&openfiles, 1) + 1;
1844 if ((openfiles_new >= maxuserfiles &&
1845 priv_check(td, PRIV_MAXFILES3) != 0) ||
1846 openfiles_new >= maxfiles) {
1847 atomic_subtract_int(&openfiles, 1);
1848 if (ppsratecheck(&lastfail, &curfail, 1)) {
1849 printf("kern.maxfiles limit exceeded by uid %i, (%s) "
1850 "please see tuning(7).\n", td->td_ucred->cr_ruid, td->td_proc->p_comm);
1851 }
1852 return (ENFILE23);
1853 }
1854 fp = uma_zalloc(file_zone, M_WAITOK0x0002);
1855 bzero(fp, sizeof(*fp))__builtin_memset((fp), 0, (sizeof(*fp)));
1856 refcount_init(&fp->f_count, 1);
1857 fp->f_cred = crhold(td->td_ucred);
1858 fp->f_ops = &badfileops;
1859 *resultfp = fp;
1860 return (0);
1861}
1862
1863/*
1864 * Install a file in a file descriptor table.
1865 */
1866void
1867_finstall(struct filedesc *fdp, struct file *fp, int fd, int flags,
1868 struct filecaps *fcaps)
1869{
1870 struct filedescent *fde;
1871
1872 MPASS(fp != NULL)do { if (__builtin_expect((!((fp != ((void *)0)))), 0)) panic
("Assertion %s failed at %s:%d", "fp != NULL", "/root/freebsd/sys/kern/kern_descrip.c"
, 1872); } while (0)
;
1873 if (fcaps != NULL((void *)0))
1874 filecaps_validate(fcaps, __func__);
1875 FILEDESC_XLOCK_ASSERT(fdp)_sx_assert(((&(fdp)->fd_sx)), ((0x00000004 | 0x00000010
)), ("/root/freebsd/sys/kern/kern_descrip.c"), (1875))
;
1876
1877 fde = &fdp->fd_ofilesfd_files->fdt_ofiles[fd];
1878#ifdef CAPABILITIES1
1879 seq_write_begin(&fde->fde_seq);
1880#endif
1881 fde->fde_file = fp;
1882 fde->fde_flags = (flags & O_CLOEXEC0x00100000) != 0 ? UF_EXCLOSE0x01 : 0;
1883 if (fcaps != NULL((void *)0))
1884 filecaps_move(fcaps, &fde->fde_caps);
1885 else
1886 filecaps_fill(&fde->fde_caps);
1887#ifdef CAPABILITIES1
1888 seq_write_end(&fde->fde_seq);
1889#endif
1890}
1891
1892int
1893finstall(struct thread *td, struct file *fp, int *fd, int flags,
1894 struct filecaps *fcaps)
1895{
1896 struct filedesc *fdp = td->td_proc->p_fd;
1897 int error;
1898
1899 MPASS(fd != NULL)do { if (__builtin_expect((!((fd != ((void *)0)))), 0)) panic
("Assertion %s failed at %s:%d", "fd != NULL", "/root/freebsd/sys/kern/kern_descrip.c"
, 1899); } while (0)
;
1900
1901 FILEDESC_XLOCK(fdp)(void)_sx_xlock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (1901))
;
1902 if ((error = fdalloc(td, 0, fd))) {
1903 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (1903))
;
1904 return (error);
1905 }
1906 fhold(fp)(refcount_acquire(&(fp)->f_count));
1907 _finstall(fdp, fp, *fd, flags, fcaps);
1908 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (1908))
;
1909 return (0);
1910}
1911
1912/*
1913 * Build a new filedesc structure from another.
1914 * Copy the current, root, and jail root vnode references.
1915 *
1916 * If fdp is not NULL, return with it shared locked.
1917 */
1918struct filedesc *
1919fdinit(struct filedesc *fdp, bool prepfiles)
1920{
1921 struct filedesc0 *newfdp0;
1922 struct filedesc *newfdp;
1923
1924 newfdp0 = uma_zalloc(filedesc0_zone, M_WAITOK0x0002 | M_ZERO0x0100);
1925 newfdp = &newfdp0->fd_fd;
1926
1927 /* Create the file descriptor table. */
1928 FILEDESC_LOCK_INIT(newfdp)sx_init_flags((&(newfdp)->fd_sx), ("filedesc structure"
), 0)
;
1929 refcount_init(&newfdp->fd_refcnt, 1);
1930 refcount_init(&newfdp->fd_holdcnt, 1);
1931 newfdp->fd_cmask = CMASK022;
1932 newfdp->fd_map = newfdp0->fd_dmap;
1933 newfdp->fd_lastfile = -1;
1934 newfdp->fd_files = (struct fdescenttbl *)&newfdp0->fd_dfiles;
1935 newfdp->fd_files->fdt_nfiles = NDFILE20;
1936
1937 if (fdp == NULL((void *)0))
1938 return (newfdp);
1939
1940 if (prepfiles && fdp->fd_lastfile >= newfdp->fd_nfilesfd_files->fdt_nfiles)
1941 fdgrowtable(newfdp, fdp->fd_lastfile + 1);
1942
1943 FILEDESC_SLOCK(fdp)(void)_sx_slock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (1943))
;
1944 newfdp->fd_cdir = fdp->fd_cdir;
1945 if (newfdp->fd_cdir)
1946 vrefact(newfdp->fd_cdir);
1947 newfdp->fd_rdir = fdp->fd_rdir;
1948 if (newfdp->fd_rdir)
1949 vrefact(newfdp->fd_rdir);
1950 newfdp->fd_jdir = fdp->fd_jdir;
1951 if (newfdp->fd_jdir)
1952 vrefact(newfdp->fd_jdir);
1953
1954 if (!prepfiles) {
1955 FILEDESC_SUNLOCK(fdp)_sx_sunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (1955))
;
1956 } else {
1957 while (fdp->fd_lastfile >= newfdp->fd_nfilesfd_files->fdt_nfiles) {
1958 FILEDESC_SUNLOCK(fdp)_sx_sunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (1958))
;
1959 fdgrowtable(newfdp, fdp->fd_lastfile + 1);
1960 FILEDESC_SLOCK(fdp)(void)_sx_slock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (1960))
;
1961 }
1962 }
1963
1964 return (newfdp);
1965}
1966
1967static struct filedesc *
1968fdhold(struct proc *p)
1969{
1970 struct filedesc *fdp;
1971
1972 PROC_LOCK_ASSERT(p, MA_OWNED)__mtx_assert(&(((&(p)->p_mtx)))->mtx_lock, (((0x00000004
))), ("/root/freebsd/sys/kern/kern_descrip.c"), (1972))
;
1973 fdp = p->p_fd;
1974 if (fdp != NULL((void *)0))
1975 refcount_acquire(&fdp->fd_holdcnt);
1976 return (fdp);
1977}
1978
1979static void
1980fddrop(struct filedesc *fdp)
1981{
1982
1983 if (fdp->fd_holdcnt > 1) {
1984 if (refcount_release(&fdp->fd_holdcnt) == 0)
1985 return;
1986 }
1987
1988 FILEDESC_LOCK_DESTROY(fdp)sx_destroy(&(fdp)->fd_sx);
1989 uma_zfree(filedesc0_zone, fdp);
1990}
1991
1992/*
1993 * Share a filedesc structure.
1994 */
1995struct filedesc *
1996fdshare(struct filedesc *fdp)
1997{
1998
1999 refcount_acquire(&fdp->fd_refcnt);
2000 return (fdp);
2001}
2002
2003/*
2004 * Unshare a filedesc structure, if necessary by making a copy
2005 */
2006void
2007fdunshare(struct thread *td)
2008{
2009 struct filedesc *tmp;
2010 struct proc *p = td->td_proc;
2011
2012 if (p->p_fd->fd_refcnt == 1)
2013 return;
2014
2015 tmp = fdcopy(p->p_fd);
2016 fdescfree(td);
2017 p->p_fd = tmp;
2018}
2019
2020void
2021fdinstall_remapped(struct thread *td, struct filedesc *fdp)
2022{
2023
2024 fdescfree(td);
2025 td->td_proc->p_fd = fdp;
2026}
2027
2028/*
2029 * Copy a filedesc structure. A NULL pointer in returns a NULL reference,
2030 * this is to ease callers, not catch errors.
2031 */
2032struct filedesc *
2033fdcopy(struct filedesc *fdp)
2034{
2035 struct filedesc *newfdp;
2036 struct filedescent *nfde, *ofde;
2037 int i;
2038
2039 MPASS(fdp != NULL)do { if (__builtin_expect((!((fdp != ((void *)0)))), 0)) panic
("Assertion %s failed at %s:%d", "fdp != NULL", "/root/freebsd/sys/kern/kern_descrip.c"
, 2039); } while (0)
;
2040
2041 newfdp = fdinit(fdp, true1);
2042 /* copy all passable descriptors (i.e. not kqueue) */
2043 newfdp->fd_freefile = -1;
2044 for (i = 0; i <= fdp->fd_lastfile; ++i) {
2045 ofde = &fdp->fd_ofilesfd_files->fdt_ofiles[i];
2046 if (ofde->fde_file == NULL((void *)0) ||
2047 (ofde->fde_file->f_ops->fo_flags & DFLAG_PASSABLE0x01) == 0) {
2048 if (newfdp->fd_freefile == -1)
2049 newfdp->fd_freefile = i;
2050 continue;
2051 }
2052 nfde = &newfdp->fd_ofilesfd_files->fdt_ofiles[i];
2053 *nfde = *ofde;
2054 filecaps_copy(&ofde->fde_caps, &nfde->fde_caps, true1);
2055 fhold(nfde->fde_file)(refcount_acquire(&(nfde->fde_file)->f_count));
2056 fdused_init(newfdp, i);
2057 newfdp->fd_lastfile = i;
2058 }
2059 if (newfdp->fd_freefile == -1)
2060 newfdp->fd_freefile = i;
2061 newfdp->fd_cmask = fdp->fd_cmask;
2062 FILEDESC_SUNLOCK(fdp)_sx_sunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (2062))
;
2063 return (newfdp);
2064}
2065
2066/*
2067 * Copies a filedesc structure, while remapping all file descriptors
2068 * stored inside using a translation table.
2069 *
2070 * File descriptors are copied over to the new file descriptor table,
2071 * regardless of whether the close-on-exec flag is set.
2072 */
2073int
2074fdcopy_remapped(struct filedesc *fdp, const int *fds, size_t nfds,
2075 struct filedesc **ret)
2076{
2077 struct filedesc *newfdp;
2078 struct filedescent *nfde, *ofde;
2079 int error, i;
2080
2081 MPASS(fdp != NULL)do { if (__builtin_expect((!((fdp != ((void *)0)))), 0)) panic
("Assertion %s failed at %s:%d", "fdp != NULL", "/root/freebsd/sys/kern/kern_descrip.c"
, 2081); } while (0)
;
2082
2083 newfdp = fdinit(fdp, true1);
2084 if (nfds > fdp->fd_lastfile + 1) {
2085 /* New table cannot be larger than the old one. */
2086 error = E2BIG7;
2087 goto bad;
2088 }
2089 /* Copy all passable descriptors (i.e. not kqueue). */
2090 newfdp->fd_freefile = nfds;
2091 for (i = 0; i < nfds; ++i) {
2092 if (fds[i] < 0 || fds[i] > fdp->fd_lastfile) {
2093 /* File descriptor out of bounds. */
2094 error = EBADF9;
2095 goto bad;
2096 }
2097 ofde = &fdp->fd_ofilesfd_files->fdt_ofiles[fds[i]];
2098 if (ofde->fde_file == NULL((void *)0)) {
2099 /* Unused file descriptor. */
2100 error = EBADF9;
2101 goto bad;
2102 }
2103 if ((ofde->fde_file->f_ops->fo_flags & DFLAG_PASSABLE0x01) == 0) {
2104 /* File descriptor cannot be passed. */
2105 error = EINVAL22;
2106 goto bad;
2107 }
2108 nfde = &newfdp->fd_ofilesfd_files->fdt_ofiles[i];
2109 *nfde = *ofde;
2110 filecaps_copy(&ofde->fde_caps, &nfde->fde_caps, true1);
2111 fhold(nfde->fde_file)(refcount_acquire(&(nfde->fde_file)->f_count));
2112 fdused_init(newfdp, i);
2113 newfdp->fd_lastfile = i;
2114 }
2115 newfdp->fd_cmask = fdp->fd_cmask;
2116 FILEDESC_SUNLOCK(fdp)_sx_sunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (2116))
;
2117 *ret = newfdp;
2118 return (0);
2119bad:
2120 FILEDESC_SUNLOCK(fdp)_sx_sunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (2120))
;
2121 fdescfree_remapped(newfdp);
2122 return (error);
2123}
2124
2125/*
2126 * Clear POSIX style locks. This is only used when fdp looses a reference (i.e.
2127 * one of processes using it exits) and the table used to be shared.
2128 */
2129static void
2130fdclearlocks(struct thread *td)
2131{
2132 struct filedesc *fdp;
2133 struct filedesc_to_leader *fdtol;
2134 struct flock lf;
2135 struct file *fp;
2136 struct proc *p;
2137 struct vnode *vp;
2138 int i;
2139
2140 p = td->td_proc;
2141 fdp = p->p_fd;
2142 fdtol = p->p_fdtol;
2143 MPASS(fdtol != NULL)do { if (__builtin_expect((!((fdtol != ((void *)0)))), 0)) panic
("Assertion %s failed at %s:%d", "fdtol != NULL", "/root/freebsd/sys/kern/kern_descrip.c"
, 2143); } while (0)
;
2144
2145 FILEDESC_XLOCK(fdp)(void)_sx_xlock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (2145))
;
2146 KASSERT(fdtol->fdl_refcount > 0,do { if (__builtin_expect((!(fdtol->fdl_refcount > 0)),
0)) panic ("filedesc_to_refcount botch: fdl_refcount=%d", fdtol
->fdl_refcount); } while (0)
2147 ("filedesc_to_refcount botch: fdl_refcount=%d",do { if (__builtin_expect((!(fdtol->fdl_refcount > 0)),
0)) panic ("filedesc_to_refcount botch: fdl_refcount=%d", fdtol
->fdl_refcount); } while (0)
2148 fdtol->fdl_refcount))do { if (__builtin_expect((!(fdtol->fdl_refcount > 0)),
0)) panic ("filedesc_to_refcount botch: fdl_refcount=%d", fdtol
->fdl_refcount); } while (0)
;
2149 if (fdtol->fdl_refcount == 1 &&
2150 (p->p_leader->p_flag & P_ADVLOCK0x00001) != 0) {
2151 for (i = 0; i <= fdp->fd_lastfile; i++) {
2152 fp = fdp->fd_ofilesfd_files->fdt_ofiles[i].fde_file;
2153 if (fp == NULL((void *)0) || fp->f_type != DTYPE_VNODE1)
2154 continue;
2155 fhold(fp)(refcount_acquire(&(fp)->f_count));
2156 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (2156))
;
2157 lf.l_whence = SEEK_SET0;
2158 lf.l_start = 0;
2159 lf.l_len = 0;
2160 lf.l_type = F_UNLCK2;
2161 vp = fp->f_vnode;
2162 (void) VOP_ADVLOCK(vp,
2163 (caddr_t)p->p_leader, F_UNLCK2,
2164 &lf, F_POSIX0x040);
2165 FILEDESC_XLOCK(fdp)(void)_sx_xlock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (2165))
;
2166 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
2167 }
2168 }
2169retry:
2170 if (fdtol->fdl_refcount == 1) {
2171 if (fdp->fd_holdleaderscount > 0 &&
2172 (p->p_leader->p_flag & P_ADVLOCK0x00001) != 0) {
2173 /*
2174 * close() or kern_dup() has cleared a reference
2175 * in a shared file descriptor table.
2176 */
2177 fdp->fd_holdleaderswakeup = 1;
2178 sx_sleep(&fdp->fd_holdleaderscount,_sleep((&fdp->fd_holdleaderscount), &((&(fdp)->
fd_sx))->lock_object, (((80) + 32)), ("fdlhold"), tick_sbt
* (0), 0, 0x0100)
2179 FILEDESC_LOCK(fdp), PLOCK, "fdlhold", 0)_sleep((&fdp->fd_holdleaderscount), &((&(fdp)->
fd_sx))->lock_object, (((80) + 32)), ("fdlhold"), tick_sbt
* (0), 0, 0x0100)
;
2180 goto retry;
2181 }
2182 if (fdtol->fdl_holdcount > 0) {
2183 /*
2184 * Ensure that fdtol->fdl_leader remains
2185 * valid in closef().
2186 */
2187 fdtol->fdl_wakeup = 1;
2188 sx_sleep(fdtol, FILEDESC_LOCK(fdp), PLOCK,_sleep((fdtol), &((&(fdp)->fd_sx))->lock_object
, (((80) + 32)), ("fdlhold"), tick_sbt * (0), 0, 0x0100)
2189 "fdlhold", 0)_sleep((fdtol), &((&(fdp)->fd_sx))->lock_object
, (((80) + 32)), ("fdlhold"), tick_sbt * (0), 0, 0x0100)
;
2190 goto retry;
2191 }
2192 }
2193 fdtol->fdl_refcount--;
2194 if (fdtol->fdl_refcount == 0 &&
2195 fdtol->fdl_holdcount == 0) {
2196 fdtol->fdl_next->fdl_prev = fdtol->fdl_prev;
2197 fdtol->fdl_prev->fdl_next = fdtol->fdl_next;
2198 } else
2199 fdtol = NULL((void *)0);
2200 p->p_fdtol = NULL((void *)0);
2201 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (2201))
;
2202 if (fdtol != NULL((void *)0))
2203 free(fdtol, M_FILEDESC_TO_LEADER);
2204}
2205
2206/*
2207 * Release a filedesc structure.
2208 */
2209static void
2210fdescfree_fds(struct thread *td, struct filedesc *fdp, bool needclose)
2211{
2212 struct filedesc0 *fdp0;
2213 struct freetable *ft, *tft;
2214 struct filedescent *fde;
2215 struct file *fp;
2216 int i;
2217
2218 for (i = 0; i <= fdp->fd_lastfile; i++) {
2219 fde = &fdp->fd_ofilesfd_files->fdt_ofiles[i];
2220 fp = fde->fde_file;
2221 if (fp != NULL((void *)0)) {
2222 fdefree_last(fde);
2223 if (needclose)
2224 (void) closef(fp, td);
2225 else
2226 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
2227 }
2228 }
2229
2230 if (NDSLOTS(fdp->fd_nfiles)(((fdp->fd_files->fdt_nfiles) + (sizeof(u_long) * 8) - 1
) / (sizeof(u_long) * 8))
> NDSLOTS(NDFILE)(((20) + (sizeof(u_long) * 8) - 1) / (sizeof(u_long) * 8)))
2231 free(fdp->fd_map, M_FILEDESC);
2232 if (fdp->fd_nfilesfd_files->fdt_nfiles > NDFILE20)
2233 free(fdp->fd_files, M_FILEDESC);
2234
2235 fdp0 = (struct filedesc0 *)fdp;
2236 SLIST_FOREACH_SAFE(ft, &fdp0->fd_free, ft_next, tft)for ((ft) = (((&fdp0->fd_free))->slh_first); (ft) &&
((tft) = (((ft))->ft_next.sle_next), 1); (ft) = (tft))
2237 free(ft->ft_table, M_FILEDESC);
2238
2239 fddrop(fdp);
2240}
2241
2242void
2243fdescfree(struct thread *td)
2244{
2245 struct proc *p;
2246 struct filedesc *fdp;
2247 struct vnode *cdir, *jdir, *rdir;
2248
2249 p = td->td_proc;
2250 fdp = p->p_fd;
2251 MPASS(fdp != NULL)do { if (__builtin_expect((!((fdp != ((void *)0)))), 0)) panic
("Assertion %s failed at %s:%d", "fdp != NULL", "/root/freebsd/sys/kern/kern_descrip.c"
, 2251); } while (0)
;
2252
2253#ifdef RACCT1
2254 if (RACCT_ENABLED()__builtin_expect((racct_enable), 0))
2255 racct_set_unlocked(p, RACCT_NOFILE7, 0);
2256#endif
2257
2258 if (p->p_fdtol != NULL((void *)0))
2259 fdclearlocks(td);
2260
2261 PROC_LOCK(p)__mtx_lock_flags(&((((&(p)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (2261))
;
2262 p->p_fd = NULL((void *)0);
2263 PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (2263))
;
2264
2265 if (refcount_release(&fdp->fd_refcnt) == 0)
2266 return;
2267
2268 FILEDESC_XLOCK(fdp)(void)_sx_xlock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (2268))
;
2269 cdir = fdp->fd_cdir;
2270 fdp->fd_cdir = NULL((void *)0);
2271 rdir = fdp->fd_rdir;
2272 fdp->fd_rdir = NULL((void *)0);
2273 jdir = fdp->fd_jdir;
2274 fdp->fd_jdir = NULL((void *)0);
2275 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (2275))
;
2276
2277 if (cdir != NULL((void *)0))
2278 vrele(cdir);
2279 if (rdir != NULL((void *)0))
2280 vrele(rdir);
2281 if (jdir != NULL((void *)0))
2282 vrele(jdir);
2283
2284 fdescfree_fds(td, fdp, 1);
2285}
2286
2287void
2288fdescfree_remapped(struct filedesc *fdp)
2289{
2290
2291 if (fdp->fd_cdir != NULL((void *)0))
2292 vrele(fdp->fd_cdir);
2293 if (fdp->fd_rdir != NULL((void *)0))
2294 vrele(fdp->fd_rdir);
2295 if (fdp->fd_jdir != NULL((void *)0))
2296 vrele(fdp->fd_jdir);
2297
2298 fdescfree_fds(curthread(__curthread()), fdp, 0);
2299}
2300
2301/*
2302 * For setugid programs, we don't want to people to use that setugidness
2303 * to generate error messages which write to a file which otherwise would
2304 * otherwise be off-limits to the process. We check for filesystems where
2305 * the vnode can change out from under us after execve (like [lin]procfs).
2306 *
2307 * Since fdsetugidsafety calls this only for fd 0, 1 and 2, this check is
2308 * sufficient. We also don't check for setugidness since we know we are.
2309 */
2310static bool
2311is_unsafe(struct file *fp)
2312{
2313 struct vnode *vp;
2314
2315 if (fp->f_type != DTYPE_VNODE1)
2316 return (false0);
2317
2318 vp = fp->f_vnode;
2319 return ((vp->v_vflag & VV_PROCDEP0x0100) != 0);
2320}
2321
2322/*
2323 * Make this setguid thing safe, if at all possible.
2324 */
2325void
2326fdsetugidsafety(struct thread *td)
2327{
2328 struct filedesc *fdp;
2329 struct file *fp;
2330 int i;
2331
2332 fdp = td->td_proc->p_fd;
2333 KASSERT(fdp->fd_refcnt == 1, ("the fdtable should not be shared"))do { if (__builtin_expect((!(fdp->fd_refcnt == 1)), 0)) panic
("the fdtable should not be shared"); } while (0)
;
2334 MPASS(fdp->fd_nfiles >= 3)do { if (__builtin_expect((!((fdp->fd_files->fdt_nfiles
>= 3))), 0)) panic ("Assertion %s failed at %s:%d", "fdp->fd_nfiles >= 3"
, "/root/freebsd/sys/kern/kern_descrip.c", 2334); } while (0)
;
2335 for (i = 0; i <= 2; i++) {
2336 fp = fdp->fd_ofilesfd_files->fdt_ofiles[i].fde_file;
2337 if (fp != NULL((void *)0) && is_unsafe(fp)) {
2338 FILEDESC_XLOCK(fdp)(void)_sx_xlock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (2338))
;
2339 knote_fdclose(td, i);
2340 /*
2341 * NULL-out descriptor prior to close to avoid
2342 * a race while close blocks.
2343 */
2344 fdfree(fdp, i);
2345 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (2345))
;
2346 (void) closef(fp, td);
2347 }
2348 }
2349}
2350
2351/*
2352 * If a specific file object occupies a specific file descriptor, close the
2353 * file descriptor entry and drop a reference on the file object. This is a
2354 * convenience function to handle a subsequent error in a function that calls
2355 * falloc() that handles the race that another thread might have closed the
2356 * file descriptor out from under the thread creating the file object.
2357 */
2358void
2359fdclose(struct thread *td, struct file *fp, int idx)
2360{
2361 struct filedesc *fdp = td->td_proc->p_fd;
2362
2363 FILEDESC_XLOCK(fdp)(void)_sx_xlock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (2363))
;
2364 if (fdp->fd_ofilesfd_files->fdt_ofiles[idx].fde_file == fp) {
2365 fdfree(fdp, idx);
2366 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (2366))
;
2367 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
2368 } else
2369 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (2369))
;
2370}
2371
2372/*
2373 * Close any files on exec?
2374 */
2375void
2376fdcloseexec(struct thread *td)
2377{
2378 struct filedesc *fdp;
2379 struct filedescent *fde;
2380 struct file *fp;
2381 int i;
2382
2383 fdp = td->td_proc->p_fd;
2384 KASSERT(fdp->fd_refcnt == 1, ("the fdtable should not be shared"))do { if (__builtin_expect((!(fdp->fd_refcnt == 1)), 0)) panic
("the fdtable should not be shared"); } while (0)
;
2385 for (i = 0; i <= fdp->fd_lastfile; i++) {
2386 fde = &fdp->fd_ofilesfd_files->fdt_ofiles[i];
2387 fp = fde->fde_file;
2388 if (fp != NULL((void *)0) && (fp->f_type == DTYPE_MQUEUE7 ||
2389 (fde->fde_flags & UF_EXCLOSE0x01))) {
2390 FILEDESC_XLOCK(fdp)(void)_sx_xlock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (2390))
;
2391 fdfree(fdp, i);
2392 (void) closefp(fdp, i, fp, td, 0);
2393 FILEDESC_UNLOCK_ASSERT(fdp)_sx_assert(((&(fdp)->fd_sx)), ((0x00000000)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (2393))
;
2394 }
2395 }
2396}
2397
2398/*
2399 * It is unsafe for set[ug]id processes to be started with file
2400 * descriptors 0..2 closed, as these descriptors are given implicit
2401 * significance in the Standard C library. fdcheckstd() will create a
2402 * descriptor referencing /dev/null for each of stdin, stdout, and
2403 * stderr that is not already open.
2404 */
2405int
2406fdcheckstd(struct thread *td)
2407{
2408 struct filedesc *fdp;
2409 register_t save;
2410 int i, error, devnull;
2411
2412 fdp = td->td_proc->p_fd;
2413 KASSERT(fdp->fd_refcnt == 1, ("the fdtable should not be shared"))do { if (__builtin_expect((!(fdp->fd_refcnt == 1)), 0)) panic
("the fdtable should not be shared"); } while (0)
;
2414 MPASS(fdp->fd_nfiles >= 3)do { if (__builtin_expect((!((fdp->fd_files->fdt_nfiles
>= 3))), 0)) panic ("Assertion %s failed at %s:%d", "fdp->fd_nfiles >= 3"
, "/root/freebsd/sys/kern/kern_descrip.c", 2414); } while (0)
;
2415 devnull = -1;
2416 for (i = 0; i <= 2; i++) {
2417 if (fdp->fd_ofilesfd_files->fdt_ofiles[i].fde_file != NULL((void *)0))
2418 continue;
2419
2420 save = td->td_retvaltd_uretoff.tdu_retval[0];
2421 if (devnull != -1) {
2422 error = kern_dup(td, FDDUP_FIXED, 0, devnull, i);
2423 } else {
2424 error = kern_openat(td, AT_FDCWD-100, "/dev/null",
2425 UIO_SYSSPACE, O_RDWR0x0002, 0);
2426 if (error == 0) {
2427 devnull = td->td_retvaltd_uretoff.tdu_retval[0];
2428 KASSERT(devnull == i, ("we didn't get our fd"))do { if (__builtin_expect((!(devnull == i)), 0)) panic ("we didn't get our fd"
); } while (0)
;
2429 }
2430 }
2431 td->td_retvaltd_uretoff.tdu_retval[0] = save;
2432 if (error != 0)
2433 return (error);
2434 }
2435 return (0);
2436}
2437
2438/*
2439 * Internal form of close. Decrement reference count on file structure.
2440 * Note: td may be NULL when closing a file that was being passed in a
2441 * message.
2442 *
2443 * XXXRW: Giant is not required for the caller, but often will be held; this
2444 * makes it moderately likely the Giant will be recursed in the VFS case.
2445 */
2446int
2447closef(struct file *fp, struct thread *td)
2448{
2449 struct vnode *vp;
2450 struct flock lf;
2451 struct filedesc_to_leader *fdtol;
2452 struct filedesc *fdp;
2453
2454 /*
2455 * POSIX record locking dictates that any close releases ALL
2456 * locks owned by this process. This is handled by setting
2457 * a flag in the unlock to free ONLY locks obeying POSIX
2458 * semantics, and not to free BSD-style file locks.
2459 * If the descriptor was in a message, POSIX-style locks
2460 * aren't passed with the descriptor, and the thread pointer
2461 * will be NULL. Callers should be careful only to pass a
2462 * NULL thread pointer when there really is no owning
2463 * context that might have locks, or the locks will be
2464 * leaked.
2465 */
2466 if (fp->f_type == DTYPE_VNODE1 && td != NULL((void *)0)) {
2467 vp = fp->f_vnode;
2468 if ((td->td_proc->p_leader->p_flag & P_ADVLOCK0x00001) != 0) {
2469 lf.l_whence = SEEK_SET0;
2470 lf.l_start = 0;
2471 lf.l_len = 0;
2472 lf.l_type = F_UNLCK2;
2473 (void) VOP_ADVLOCK(vp, (caddr_t)td->td_proc->p_leader,
2474 F_UNLCK2, &lf, F_POSIX0x040);
2475 }
2476 fdtol = td->td_proc->p_fdtol;
2477 if (fdtol != NULL((void *)0)) {
2478 /*
2479 * Handle special case where file descriptor table is
2480 * shared between multiple process leaders.
2481 */
2482 fdp = td->td_proc->p_fd;
2483 FILEDESC_XLOCK(fdp)(void)_sx_xlock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (2483))
;
2484 for (fdtol = fdtol->fdl_next;
2485 fdtol != td->td_proc->p_fdtol;
2486 fdtol = fdtol->fdl_next) {
2487 if ((fdtol->fdl_leader->p_flag &
2488 P_ADVLOCK0x00001) == 0)
2489 continue;
2490 fdtol->fdl_holdcount++;
2491 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (2491))
;
2492 lf.l_whence = SEEK_SET0;
2493 lf.l_start = 0;
2494 lf.l_len = 0;
2495 lf.l_type = F_UNLCK2;
2496 vp = fp->f_vnode;
2497 (void) VOP_ADVLOCK(vp,
2498 (caddr_t)fdtol->fdl_leader, F_UNLCK2, &lf,
2499 F_POSIX0x040);
2500 FILEDESC_XLOCK(fdp)(void)_sx_xlock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (2500))
;
2501 fdtol->fdl_holdcount--;
2502 if (fdtol->fdl_holdcount == 0 &&
2503 fdtol->fdl_wakeup != 0) {
2504 fdtol->fdl_wakeup = 0;
2505 wakeup(fdtol);
2506 }
2507 }
2508 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (2508))
;
2509 }
2510 }
2511 return (fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
);
2512}
2513
2514/*
2515 * Initialize the file pointer with the specified properties.
2516 *
2517 * The ops are set with release semantics to be certain that the flags, type,
2518 * and data are visible when ops is. This is to prevent ops methods from being
2519 * called with bad data.
2520 */
2521void
2522finit(struct file *fp, u_int flag, short type, void *data, struct fileops *ops)
2523{
2524 fp->f_data = data;
2525 fp->f_flag = flag;
2526 fp->f_type = type;
2527 atomic_store_rel_ptratomic_store_rel_long((volatile uintptr_t *)&fp->f_ops, (uintptr_t)ops);
2528}
2529
2530int
2531fget_cap_locked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
2532 struct file **fpp, struct filecaps *havecapsp)
2533{
2534 struct filedescent *fde;
2535 int error;
2536
2537 FILEDESC_LOCK_ASSERT(fdp)_sx_assert(((&(fdp)->fd_sx)), ((0x00000001 | 0x00000010
)), ("/root/freebsd/sys/kern/kern_descrip.c"), (2537))
;
2538
2539 fde = fdeget_locked(fdp, fd);
2540 if (fde == NULL((void *)0)) {
2541 error = EBADF9;
2542 goto out;
2543 }
2544
2545#ifdef CAPABILITIES1
2546 error = cap_check(cap_rights_fde_inline(fde)(&(fde)->fde_caps.fc_rights), needrightsp);
2547 if (error != 0)
2548 goto out;
2549#endif
2550
2551 if (havecapsp != NULL((void *)0))
2552 filecaps_copy(&fde->fde_caps, havecapsp, true1);
2553
2554 *fpp = fde->fde_file;
2555
2556 error = 0;
2557out:
2558 return (error);
2559}
2560
2561int
2562fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp,
2563 struct file **fpp, struct filecaps *havecapsp)
2564{
2565 struct filedesc *fdp = td->td_proc->p_fd;
2566 int error;
2567#ifndef CAPABILITIES1
2568 error = fget_unlocked(fdp, fd, needrightsp, fpp, NULL((void *)0));
2569 if (error == 0 && havecapsp != NULL((void *)0))
2570 filecaps_fill(havecapsp);
2571#else
2572 struct file *fp;
2573 seq_t seq;
2574
2575 for (;;) {
2576 error = fget_unlocked(fdp, fd, needrightsp, &fp, &seq);
2577 if (error != 0)
2578 return (error);
2579
2580 if (havecapsp != NULL((void *)0)) {
2581 if (!filecaps_copy(&fdp->fd_ofilesfd_files->fdt_ofiles[fd].fde_caps,
2582 havecapsp, false0)) {
2583 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
2584 goto get_locked;
2585 }
2586 }
2587
2588 if (!fd_modified(fdp, fd, seq))
2589 break;
2590 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
2591 }
2592
2593 *fpp = fp;
2594 return (0);
2595
2596get_locked:
2597 FILEDESC_SLOCK(fdp)(void)_sx_slock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (2597))
;
2598 error = fget_cap_locked(fdp, fd, needrightsp, fpp, havecapsp);
2599 if (error == 0)
2600 fhold(*fpp)(refcount_acquire(&(*fpp)->f_count));
2601 FILEDESC_SUNLOCK(fdp)_sx_sunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (2601))
;
2602#endif
2603 return (error);
2604}
2605
2606int
2607fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
2608 struct file **fpp, seq_t *seqp)
2609{
2610#ifdef CAPABILITIES1
2611 const struct filedescent *fde;
2612#endif
2613 const struct fdescenttbl *fdt;
2614 struct file *fp;
2615 u_int count;
2616#ifdef CAPABILITIES1
2617 seq_t seq;
2618 cap_rights_t haverights;
2619 int error;
2620#endif
2621
2622 fdt = fdp->fd_files;
2623 if (__predict_false((u_int)fd >= fdt->fdt_nfiles)__builtin_expect(((u_int)fd >= fdt->fdt_nfiles), 0))
2624 return (EBADF9);
2625 /*
2626 * Fetch the descriptor locklessly. We avoid fdrop() races by
2627 * never raising a refcount above 0. To accomplish this we have
2628 * to use a cmpset loop rather than an atomic_add. The descriptor
2629 * must be re-verified once we acquire a reference to be certain
2630 * that the identity is still correct and we did not lose a race
2631 * due to preemption.
2632 */
2633 for (;;) {
2634#ifdef CAPABILITIES1
2635 seq = seq_read(fd_seq(fdt, fd)(&(fdt)->fdt_ofiles[(fd)].fde_seq));
2636 fde = &fdt->fdt_ofiles[fd];
2637 haverights = *cap_rights_fde_inline(fde)(&(fde)->fde_caps.fc_rights);
2638 fp = fde->fde_file;
2639 if (!seq_consistent(fd_seq(fdt, fd)(&(fdt)->fdt_ofiles[(fd)].fde_seq), seq))
2640 continue;
2641#else
2642 fp = fdt->fdt_ofiles[fd].fde_file;
2643#endif
2644 if (fp == NULL((void *)0))
2645 return (EBADF9);
2646#ifdef CAPABILITIES1
2647 error = cap_check(&haverights, needrightsp);
2648 if (error != 0)
2649 return (error);
2650#endif
2651 count = fp->f_count;
2652 retry:
2653 if (count == 0) {
2654 /*
2655 * Force a reload. Other thread could reallocate the
2656 * table before this fd was closed, so it possible that
2657 * there is a stale fp pointer in cached version.
2658 */
2659 fdt = *(const struct fdescenttbl * const volatile *)&(fdp->fd_files);
2660 continue;
2661 }
2662 /*
2663 * Use an acquire barrier to force re-reading of fdt so it is
2664 * refreshed for verification.
2665 */
2666 if (atomic_fcmpset_acq_intatomic_fcmpset_int(&fp->f_count, &count, count + 1) == 0)
2667 goto retry;
2668 fdt = fdp->fd_files;
2669#ifdef CAPABILITIES1
2670 if (seq_consistent_nomb(fd_seq(fdt, fd)(&(fdt)->fdt_ofiles[(fd)].fde_seq), seq))
2671#else
2672 if (fp == fdt->fdt_ofiles[fd].fde_file)
2673#endif
2674 break;
2675 fdrop(fp, curthread)(refcount_release(&(fp)->f_count) ? _fdrop((fp), ((__curthread
()))) : _fnoop())
;
2676 }
2677 *fpp = fp;
2678 if (seqp != NULL((void *)0)) {
2679#ifdef CAPABILITIES1
2680 *seqp = seq;
2681#endif
2682 }
2683 return (0);
2684}
2685
2686/*
2687 * Extract the file pointer associated with the specified descriptor for the
2688 * current user process.
2689 *
2690 * If the descriptor doesn't exist or doesn't match 'flags', EBADF is
2691 * returned.
2692 *
2693 * File's rights will be checked against the capability rights mask.
2694 *
2695 * If an error occurred the non-zero error is returned and *fpp is set to
2696 * NULL. Otherwise *fpp is held and set and zero is returned. Caller is
2697 * responsible for fdrop().
2698 */
2699static __inline int
2700_fget(struct thread *td, int fd, struct file **fpp, int flags,
2701 cap_rights_t *needrightsp, seq_t *seqp)
2702{
2703 struct filedesc *fdp;
2704 struct file *fp;
2705 int error;
2706
2707 *fpp = NULL((void *)0);
2708 fdp = td->td_proc->p_fd;
2709 error = fget_unlocked(fdp, fd, needrightsp, &fp, seqp);
2710 if (error != 0)
2711 return (error);
2712 if (fp->f_ops == &badfileops) {
2713 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
2714 return (EBADF9);
2715 }
2716
2717 /*
2718 * FREAD and FWRITE failure return EBADF as per POSIX.
2719 */
2720 error = 0;
2721 switch (flags) {
2722 case FREAD0x0001:
2723 case FWRITE0x0002:
2724 if ((fp->f_flag & flags) == 0)
2725 error = EBADF9;
2726 break;
2727 case FEXEC0x00040000:
2728 if ((fp->f_flag & (FREAD0x0001 | FEXEC0x00040000)) == 0 ||
2729 ((fp->f_flag & FWRITE0x0002) != 0))
2730 error = EBADF9;
2731 break;
2732 case 0:
2733 break;
2734 default:
2735 KASSERT(0, ("wrong flags"))do { if (__builtin_expect((!(0)), 0)) panic ("wrong flags"); }
while (0)
;
2736 }
2737
2738 if (error != 0) {
2739 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
2740 return (error);
2741 }
2742
2743 *fpp = fp;
2744 return (0);
2745}
2746
2747int
2748fget(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp)
2749{
2750
2751 return (_fget(td, fd, fpp, 0, rightsp, NULL((void *)0)));
2752}
2753
2754int
2755fget_mmap(struct thread *td, int fd, cap_rights_t *rightsp, u_char *maxprotp,
2756 struct file **fpp)
2757{
2758 int error;
2759#ifndef CAPABILITIES1
2760 error = _fget(td, fd, fpp, 0, rightsp, NULL((void *)0));
2761 if (maxprotp != NULL((void *)0))
2762 *maxprotp = VM_PROT_ALL(((vm_prot_t) 0x01)|((vm_prot_t) 0x02)|((vm_prot_t) 0x04));
2763#else
2764 struct filedesc *fdp = td->td_proc->p_fd;
2765 seq_t seq;
2766
2767 MPASS(cap_rights_is_set(rightsp, CAP_MMAP))do { if (__builtin_expect((!((__cap_rights_is_set(rightsp, ((
1ULL << (57 + (0))) | (0x0000000000000010ULL)), 0ULL)))
), 0)) panic ("Assertion %s failed at %s:%d", "cap_rights_is_set(rightsp, CAP_MMAP)"
, "/root/freebsd/sys/kern/kern_descrip.c", 2767); } while (0)
;
2768 for (;;) {
2769 error = _fget(td, fd, fpp, 0, rightsp, &seq);
2770 if (error != 0)
2771 return (error);
2772 /*
2773 * If requested, convert capability rights to access flags.
2774 */
2775 if (maxprotp != NULL((void *)0))
2776 *maxprotp = cap_rights_to_vmprot(cap_rights(fdp, fd));
2777 if (!fd_modified(fdp, fd, seq))
2778 break;
2779 fdrop(*fpp, td)(refcount_release(&(*fpp)->f_count) ? _fdrop((*fpp), (
td)) : _fnoop())
;
2780 }
2781#endif
2782 return (error);
2783}
2784
2785int
2786fget_read(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp)
2787{
2788
2789 return (_fget(td, fd, fpp, FREAD0x0001, rightsp, NULL((void *)0)));
2790}
2791
2792int
2793fget_write(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp)
2794{
2795
2796 return (_fget(td, fd, fpp, FWRITE0x0002, rightsp, NULL((void *)0)));
2797}
2798
2799int
2800fget_fcntl(struct thread *td, int fd, cap_rights_t *rightsp, int needfcntl,
2801 struct file **fpp)
2802{
2803 struct filedesc *fdp = td->td_proc->p_fd;
2804#ifndef CAPABILITIES1
2805 return (fget_unlocked(fdp, fd, rightsp, fpp, NULL((void *)0)));
2806#else
2807 int error;
2808 seq_t seq;
2809
2810 MPASS(cap_rights_is_set(rightsp, CAP_FCNTL))do { if (__builtin_expect((!((__cap_rights_is_set(rightsp, ((
1ULL << (57 + (0))) | (0x0000000000008000ULL)), 0ULL)))
), 0)) panic ("Assertion %s failed at %s:%d", "cap_rights_is_set(rightsp, CAP_FCNTL)"
, "/root/freebsd/sys/kern/kern_descrip.c", 2810); } while (0)
;
2811 for (;;) {
2812 error = fget_unlocked(fdp, fd, rightsp, fpp, &seq);
2813 if (error != 0)
2814 return (error);
2815 error = cap_fcntl_check(fdp, fd, needfcntl);
2816 if (!fd_modified(fdp, fd, seq))
2817 break;
2818 fdrop(*fpp, td)(refcount_release(&(*fpp)->f_count) ? _fdrop((*fpp), (
td)) : _fnoop())
;
2819 }
2820 if (error != 0) {
2821 fdrop(*fpp, td)(refcount_release(&(*fpp)->f_count) ? _fdrop((*fpp), (
td)) : _fnoop())
;
2822 *fpp = NULL((void *)0);
2823 }
2824 return (error);
2825#endif
2826}
2827
2828/*
2829 * Like fget() but loads the underlying vnode, or returns an error if the
2830 * descriptor does not represent a vnode. Note that pipes use vnodes but
2831 * never have VM objects. The returned vnode will be vref()'d.
2832 *
2833 * XXX: what about the unused flags ?
2834 */
2835static __inline int
2836_fgetvp(struct thread *td, int fd, int flags, cap_rights_t *needrightsp,
2837 struct vnode **vpp)
2838{
2839 struct file *fp;
2840 int error;
2841
2842 *vpp = NULL((void *)0);
2843 error = _fget(td, fd, &fp, flags, needrightsp, NULL((void *)0));
2844 if (error != 0)
2845 return (error);
2846 if (fp->f_vnode == NULL((void *)0)) {
2847 error = EINVAL22;
2848 } else {
2849 *vpp = fp->f_vnode;
2850 vrefact(*vpp);
2851 }
2852 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
2853
2854 return (error);
2855}
2856
2857int
2858fgetvp(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp)
2859{
2860
2861 return (_fgetvp(td, fd, 0, rightsp, vpp));
2862}
2863
2864int
2865fgetvp_rights(struct thread *td, int fd, cap_rights_t *needrightsp,
2866 struct filecaps *havecaps, struct vnode **vpp)
2867{
2868 struct filedesc *fdp;
2869 struct filecaps caps;
2870 struct file *fp;
2871 int error;
2872
2873 fdp = td->td_proc->p_fd;
2874 error = fget_cap_locked(fdp, fd, needrightsp, &fp, &caps);
2875 if (error != 0)
2876 return (error);
2877 if (fp->f_ops == &badfileops) {
2878 error = EBADF9;
2879 goto out;
2880 }
2881 if (fp->f_vnode == NULL((void *)0)) {
2882 error = EINVAL22;
2883 goto out;
2884 }
2885
2886 *havecaps = caps;
2887 *vpp = fp->f_vnode;
2888 vrefact(*vpp);
2889
2890 return (0);
2891out:
2892 filecaps_free(&caps);
2893 return (error);
2894}
2895
2896int
2897fgetvp_read(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp)
2898{
2899
2900 return (_fgetvp(td, fd, FREAD0x0001, rightsp, vpp));
2901}
2902
2903int
2904fgetvp_exec(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp)
2905{
2906
2907 return (_fgetvp(td, fd, FEXEC0x00040000, rightsp, vpp));
2908}
2909
2910#ifdef notyet
2911int
2912fgetvp_write(struct thread *td, int fd, cap_rights_t *rightsp,
2913 struct vnode **vpp)
2914{
2915
2916 return (_fgetvp(td, fd, FWRITE0x0002, rightsp, vpp));
2917}
2918#endif
2919
2920/*
2921 * Handle the last reference to a file being closed.
2922 *
2923 * Without the noinline attribute clang keeps inlining the func thorough this
2924 * file when fdrop is used.
2925 */
2926int __noinline__attribute__ ((__noinline__))
2927_fdrop(struct file *fp, struct thread *td)
2928{
2929 int error;
2930
2931 if (fp->f_count != 0)
2932 panic("fdrop: count %d", fp->f_count);
2933 error = fo_close(fp, td);
2934 atomic_subtract_int(&openfiles, 1);
2935 crfree(fp->f_cred);
2936 free(fp->f_advicef_vnun.fvn_advice, M_FADVISE);
2937 uma_zfree(file_zone, fp);
2938
2939 return (error);
2940}
2941
2942/*
2943 * Apply an advisory lock on a file descriptor.
2944 *
2945 * Just attempt to get a record lock of the requested type on the entire file
2946 * (l_whence = SEEK_SET, l_start = 0, l_len = 0).
2947 */
2948#ifndef _SYS_SYSPROTO_H_
2949struct flock_args {
2950 int fd;
2951 int how;
2952};
2953#endif
2954/* ARGSUSED */
2955int
2956sys_flock(struct thread *td, struct flock_args *uap)
2957{
2958 struct file *fp;
2959 struct vnode *vp;
2960 struct flock lf;
2961 int error;
2962
2963 error = fget(td, uap->fd, &cap_flock_rights, &fp);
2964 if (error != 0)
2965 return (error);
2966 if (fp->f_type != DTYPE_VNODE1) {
2967 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
2968 return (EOPNOTSUPP45);
2969 }
2970
2971 vp = fp->f_vnode;
2972 lf.l_whence = SEEK_SET0;
2973 lf.l_start = 0;
2974 lf.l_len = 0;
2975 if (uap->how & LOCK_UN0x08) {
2976 lf.l_type = F_UNLCK2;
2977 atomic_clear_int(&fp->f_flag, FHASLOCK0x4000);
2978 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK2, &lf, F_FLOCK0x020);
2979 goto done2;
2980 }
2981 if (uap->how & LOCK_EX0x02)
2982 lf.l_type = F_WRLCK3;
2983 else if (uap->how & LOCK_SH0x01)
2984 lf.l_type = F_RDLCK1;
2985 else {
2986 error = EBADF9;
2987 goto done2;
2988 }
2989 atomic_set_int(&fp->f_flag, FHASLOCK0x4000);
2990 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK12, &lf,
2991 (uap->how & LOCK_NB0x04) ? F_FLOCK0x020 : F_FLOCK0x020 | F_WAIT0x010);
2992done2:
2993 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
2994 return (error);
2995}
2996/*
2997 * Duplicate the specified descriptor to a free descriptor.
2998 */
2999int
3000dupfdopen(struct thread *td, struct filedesc *fdp, int dfd, int mode,
3001 int openerror, int *indxp)
3002{
3003 struct filedescent *newfde, *oldfde;
3004 struct file *fp;
3005 u_long *ioctls;
3006 int error, indx;
3007
3008 KASSERT(openerror == ENODEV || openerror == ENXIO,do { if (__builtin_expect((!(openerror == 19 || openerror == 6
)), 0)) panic ("unexpected error %d in %s", openerror, __func__
); } while (0)
3009 ("unexpected error %d in %s", openerror, __func__))do { if (__builtin_expect((!(openerror == 19 || openerror == 6
)), 0)) panic ("unexpected error %d in %s", openerror, __func__
); } while (0)
;
3010
3011 /*
3012 * If the to-be-dup'd fd number is greater than the allowed number
3013 * of file descriptors, or the fd to be dup'd has already been
3014 * closed, then reject.
3015 */
3016 FILEDESC_XLOCK(fdp)(void)_sx_xlock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (3016))
;
3017 if ((fp = fget_locked(fdp, dfd)) == NULL((void *)0)) {
3018 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3018))
;
3019 return (EBADF9);
3020 }
3021
3022 error = fdalloc(td, 0, &indx);
3023 if (error != 0) {
3024 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3024))
;
3025 return (error);
3026 }
3027
3028 /*
3029 * There are two cases of interest here.
3030 *
3031 * For ENODEV simply dup (dfd) to file descriptor (indx) and return.
3032 *
3033 * For ENXIO steal away the file structure from (dfd) and store it in
3034 * (indx). (dfd) is effectively closed by this operation.
3035 */
3036 switch (openerror) {
3037 case ENODEV19:
3038 /*
3039 * Check that the mode the file is being opened for is a
3040 * subset of the mode of the existing descriptor.
3041 */
3042 if (((mode & (FREAD0x0001|FWRITE0x0002)) | fp->f_flag) != fp->f_flag) {
3043 fdunused(fdp, indx);
3044 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3044))
;
3045 return (EACCES13);
3046 }
3047 fhold(fp)(refcount_acquire(&(fp)->f_count));
3048 newfde = &fdp->fd_ofilesfd_files->fdt_ofiles[indx];
3049 oldfde = &fdp->fd_ofilesfd_files->fdt_ofiles[dfd];
3050 ioctls = filecaps_copy_prep(&oldfde->fde_caps);
3051#ifdef CAPABILITIES1
3052 seq_write_begin(&newfde->fde_seq);
3053#endif
3054 memcpy(newfde, oldfde, fde_change_size)__builtin_memcpy((newfde), (oldfde), ((__builtin_offsetof(struct
filedescent, fde_seq))))
;
3055 filecaps_copy_finish(&oldfde->fde_caps, &newfde->fde_caps,
3056 ioctls);
3057#ifdef CAPABILITIES1
3058 seq_write_end(&newfde->fde_seq);
3059#endif
3060 break;
3061 case ENXIO6:
3062 /*
3063 * Steal away the file pointer from dfd and stuff it into indx.
3064 */
3065 newfde = &fdp->fd_ofilesfd_files->fdt_ofiles[indx];
3066 oldfde = &fdp->fd_ofilesfd_files->fdt_ofiles[dfd];
3067#ifdef CAPABILITIES1
3068 seq_write_begin(&newfde->fde_seq);
3069#endif
3070 memcpy(newfde, oldfde, fde_change_size)__builtin_memcpy((newfde), (oldfde), ((__builtin_offsetof(struct
filedescent, fde_seq))))
;
3071 oldfde->fde_file = NULL((void *)0);
3072 fdunused(fdp, dfd);
3073#ifdef CAPABILITIES1
3074 seq_write_end(&newfde->fde_seq);
3075#endif
3076 break;
3077 }
3078 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3078))
;
3079 *indxp = indx;
3080 return (0);
3081}
3082
3083/*
3084 * This sysctl determines if we will allow a process to chroot(2) if it
3085 * has a directory open:
3086 * 0: disallowed for all processes.
3087 * 1: allowed for processes that were not already chroot(2)'ed.
3088 * 2: allowed for all processes.
3089 */
3090
3091static int chroot_allow_open_directories = 1;
3092
3093SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,static struct sysctl_oid sysctl___kern_chroot_allow_open_directories
= { .oid_parent = ((&(&sysctl___kern)->oid_children
)), .oid_children = { ((void *)0) }, .oid_number = ((-1)), .oid_kind
= (2 | 0x00040000 | ((0x80000000|0x40000000))), .oid_arg1 = (
&chroot_allow_open_directories), .oid_arg2 = (0), .oid_name
= ("chroot_allow_open_directories"), .oid_handler = (sysctl_handle_int
), .oid_fmt = ("I"), .oid_descr = "Allow a process to chroot(2) if it has a directory open"
, .oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___kern_chroot_allow_open_directories
__attribute__((__section__("set_" "sysctl_set"))) __attribute__
((__used__)) = &(sysctl___kern_chroot_allow_open_directories
); _Static_assert(((((0x80000000|0x40000000)) & 0xf) == 0
|| (((0x80000000|0x40000000)) & 0) == 2) && sizeof
(int) == sizeof(*(&chroot_allow_open_directories)), "compile-time assertion failed"
)
3094 &chroot_allow_open_directories, 0,static struct sysctl_oid sysctl___kern_chroot_allow_open_directories
= { .oid_parent = ((&(&sysctl___kern)->oid_children
)), .oid_children = { ((void *)0) }, .oid_number = ((-1)), .oid_kind
= (2 | 0x00040000 | ((0x80000000|0x40000000))), .oid_arg1 = (
&chroot_allow_open_directories), .oid_arg2 = (0), .oid_name
= ("chroot_allow_open_directories"), .oid_handler = (sysctl_handle_int
), .oid_fmt = ("I"), .oid_descr = "Allow a process to chroot(2) if it has a directory open"
, .oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___kern_chroot_allow_open_directories
__attribute__((__section__("set_" "sysctl_set"))) __attribute__
((__used__)) = &(sysctl___kern_chroot_allow_open_directories
); _Static_assert(((((0x80000000|0x40000000)) & 0xf) == 0
|| (((0x80000000|0x40000000)) & 0) == 2) && sizeof
(int) == sizeof(*(&chroot_allow_open_directories)), "compile-time assertion failed"
)
3095 "Allow a process to chroot(2) if it has a directory open")static struct sysctl_oid sysctl___kern_chroot_allow_open_directories
= { .oid_parent = ((&(&sysctl___kern)->oid_children
)), .oid_children = { ((void *)0) }, .oid_number = ((-1)), .oid_kind
= (2 | 0x00040000 | ((0x80000000|0x40000000))), .oid_arg1 = (
&chroot_allow_open_directories), .oid_arg2 = (0), .oid_name
= ("chroot_allow_open_directories"), .oid_handler = (sysctl_handle_int
), .oid_fmt = ("I"), .oid_descr = "Allow a process to chroot(2) if it has a directory open"
, .oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___kern_chroot_allow_open_directories
__attribute__((__section__("set_" "sysctl_set"))) __attribute__
((__used__)) = &(sysctl___kern_chroot_allow_open_directories
); _Static_assert(((((0x80000000|0x40000000)) & 0xf) == 0
|| (((0x80000000|0x40000000)) & 0) == 2) && sizeof
(int) == sizeof(*(&chroot_allow_open_directories)), "compile-time assertion failed"
)
;
3096
3097/*
3098 * Helper function for raised chroot(2) security function: Refuse if
3099 * any filedescriptors are open directories.
3100 */
3101static int
3102chroot_refuse_vdir_fds(struct filedesc *fdp)
3103{
3104 struct vnode *vp;
3105 struct file *fp;
3106 int fd;
3107
3108 FILEDESC_LOCK_ASSERT(fdp)_sx_assert(((&(fdp)->fd_sx)), ((0x00000001 | 0x00000010
)), ("/root/freebsd/sys/kern/kern_descrip.c"), (3108))
;
3109
3110 for (fd = 0; fd <= fdp->fd_lastfile; fd++) {
3111 fp = fget_locked(fdp, fd);
3112 if (fp == NULL((void *)0))
3113 continue;
3114 if (fp->f_type == DTYPE_VNODE1) {
3115 vp = fp->f_vnode;
3116 if (vp->v_type == VDIR)
3117 return (EPERM1);
3118 }
3119 }
3120 return (0);
3121}
3122
3123/*
3124 * Common routine for kern_chroot() and jail_attach(). The caller is
3125 * responsible for invoking priv_check() and mac_vnode_check_chroot() to
3126 * authorize this operation.
3127 */
3128int
3129pwd_chroot(struct thread *td, struct vnode *vp)
3130{
3131 struct filedesc *fdp;
3132 struct vnode *oldvp;
3133 int error;
3134
3135 fdp = td->td_proc->p_fd;
3136 FILEDESC_XLOCK(fdp)(void)_sx_xlock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (3136))
;
3137 if (chroot_allow_open_directories == 0 ||
3138 (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
3139 error = chroot_refuse_vdir_fds(fdp);
3140 if (error != 0) {
3141 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3141))
;
3142 return (error);
3143 }
3144 }
3145 oldvp = fdp->fd_rdir;
3146 vrefact(vp);
3147 fdp->fd_rdir = vp;
3148 if (fdp->fd_jdir == NULL((void *)0)) {
3149 vrefact(vp);
3150 fdp->fd_jdir = vp;
3151 }
3152 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3152))
;
3153 vrele(oldvp);
3154 return (0);
3155}
3156
3157void
3158pwd_chdir(struct thread *td, struct vnode *vp)
3159{
3160 struct filedesc *fdp;
3161 struct vnode *oldvp;
3162
3163 fdp = td->td_proc->p_fd;
3164 FILEDESC_XLOCK(fdp)(void)_sx_xlock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (3164))
;
3165 VNASSERT(vp->v_usecount > 0, vp,do { if (__builtin_expect((!(vp->v_usecount > 0)), 0)) {
vn_printf(vp, "VNASSERT failed\n"); panic ("chdir to a vnode with zero usecount"
); } } while (0)
3166 ("chdir to a vnode with zero usecount"))do { if (__builtin_expect((!(vp->v_usecount > 0)), 0)) {
vn_printf(vp, "VNASSERT failed\n"); panic ("chdir to a vnode with zero usecount"
); } } while (0)
;
3167 oldvp = fdp->fd_cdir;
3168 fdp->fd_cdir = vp;
3169 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3169))
;
3170 vrele(oldvp);
3171}
3172
3173/*
3174 * Scan all active processes and prisons to see if any of them have a current
3175 * or root directory of `olddp'. If so, replace them with the new mount point.
3176 */
3177void
3178mountcheckdirs(struct vnode *olddp, struct vnode *newdp)
3179{
3180 struct filedesc *fdp;
3181 struct prison *pr;
3182 struct proc *p;
3183 int nrele;
3184
3185 if (vrefcnt(olddp) == 1)
3186 return;
3187 nrele = 0;
3188 sx_slock(&allproc_lock)(void)_sx_slock(((&allproc_lock)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (3188))
;
3189 FOREACH_PROC_IN_SYSTEM(p)for (((p)) = (((&allproc))->lh_first); ((p)); ((p)) = (
(((p)))->p_list.le_next))
{
3190 PROC_LOCK(p)__mtx_lock_flags(&((((&(p)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (3190))
;
3191 fdp = fdhold(p);
3192 PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (3192))
;
3193 if (fdp == NULL((void *)0))
3194 continue;
3195 FILEDESC_XLOCK(fdp)(void)_sx_xlock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (3195))
;
3196 if (fdp->fd_cdir == olddp) {
3197 vrefact(newdp);
3198 fdp->fd_cdir = newdp;
3199 nrele++;
3200 }
3201 if (fdp->fd_rdir == olddp) {
3202 vrefact(newdp);
3203 fdp->fd_rdir = newdp;
3204 nrele++;
3205 }
3206 if (fdp->fd_jdir == olddp) {
3207 vrefact(newdp);
3208 fdp->fd_jdir = newdp;
3209 nrele++;
3210 }
3211 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3211))
;
3212 fddrop(fdp);
3213 }
3214 sx_sunlock(&allproc_lock)_sx_sunlock(((&allproc_lock)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3214))
;
3215 if (rootvnode == olddp) {
3216 vrefact(newdp);
3217 rootvnode = newdp;
3218 nrele++;
3219 }
3220 mtx_lock(&prison0.pr_mtx)__mtx_lock_flags(&((((&prison0.pr_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (3220))
;
3221 if (prison0.pr_root == olddp) {
3222 vrefact(newdp);
3223 prison0.pr_root = newdp;
3224 nrele++;
3225 }
3226 mtx_unlock(&prison0.pr_mtx)__mtx_unlock_flags(&((((&prison0.pr_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (3226))
;
3227 sx_slock(&allprison_lock)(void)_sx_slock(((&allprison_lock)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (3227))
;
3228 TAILQ_FOREACH(pr, &allprison, pr_list)for ((pr) = (((&allprison))->tqh_first); (pr); (pr) = (
((pr))->pr_list.tqe_next))
{
3229 mtx_lock(&pr->pr_mtx)__mtx_lock_flags(&((((&pr->pr_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (3229))
;
3230 if (pr->pr_root == olddp) {
3231 vrefact(newdp);
3232 pr->pr_root = newdp;
3233 nrele++;
3234 }
3235 mtx_unlock(&pr->pr_mtx)__mtx_unlock_flags(&((((&pr->pr_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (3235))
;
3236 }
3237 sx_sunlock(&allprison_lock)_sx_sunlock(((&allprison_lock)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3237))
;
3238 while (nrele--)
3239 vrele(olddp);
3240}
3241
3242struct filedesc_to_leader *
3243filedesc_to_leader_alloc(struct filedesc_to_leader *old, struct filedesc *fdp, struct proc *leader)
3244{
3245 struct filedesc_to_leader *fdtol;
3246
3247 fdtol = malloc(sizeof(struct filedesc_to_leader),
3248 M_FILEDESC_TO_LEADER, M_WAITOK0x0002);
3249 fdtol->fdl_refcount = 1;
3250 fdtol->fdl_holdcount = 0;
3251 fdtol->fdl_wakeup = 0;
3252 fdtol->fdl_leader = leader;
3253 if (old != NULL((void *)0)) {
3254 FILEDESC_XLOCK(fdp)(void)_sx_xlock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (3254))
;
3255 fdtol->fdl_next = old->fdl_next;
3256 fdtol->fdl_prev = old;
3257 old->fdl_next = fdtol;
3258 fdtol->fdl_next->fdl_prev = fdtol;
3259 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3259))
;
3260 } else {
3261 fdtol->fdl_next = fdtol;
3262 fdtol->fdl_prev = fdtol;
3263 }
3264 return (fdtol);
3265}
3266
3267static int
3268sysctl_kern_proc_nfds(SYSCTL_HANDLER_ARGSstruct sysctl_oid *oidp, void *arg1, intmax_t arg2, struct sysctl_req
*req
)
3269{
3270 struct filedesc *fdp;
3271 int i, count, slots;
3272
3273 if (*(int *)arg1 != 0)
3274 return (EINVAL22);
3275
3276 fdp = curproc((__curthread())->td_proc)->p_fd;
3277 count = 0;
3278 FILEDESC_SLOCK(fdp)(void)_sx_slock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (3278))
;
3279 slots = NDSLOTS(fdp->fd_lastfile + 1)(((fdp->fd_lastfile + 1) + (sizeof(u_long) * 8) - 1) / (sizeof
(u_long) * 8))
;
3280 for (i = 0; i < slots; i++)
3281 count += bitcountl(fdp->fd_map[i])__bitcount64((unsigned long)((u_long)(fdp->fd_map[i])));
3282 FILEDESC_SUNLOCK(fdp)_sx_sunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3282))
;
3283
3284 return (SYSCTL_OUT(req, &count, sizeof(count))(req->oldfunc)(req, &count, sizeof(count)));
3285}
3286
3287static SYSCTL_NODE(_kern_proc, KERN_PROC_NFDS, nfds,struct sysctl_oid sysctl___kern_proc_nfds = { .oid_parent = (
(&(&sysctl___kern_proc)->oid_children)), .oid_children
= { ((void *)0) }, .oid_number = (43), .oid_kind = (1|(0x80000000
|0x00008000|0x00040000)), .oid_arg1 = (((void *)0)), .oid_arg2
= (0), .oid_name = ("nfds"), .oid_handler = (sysctl_kern_proc_nfds
), .oid_fmt = ("N"), .oid_descr = "Number of open file descriptors"
, .oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___kern_proc_nfds __attribute__
((__section__("set_" "sysctl_set"))) __attribute__((__used__)
) = &(sysctl___kern_proc_nfds); _Static_assert(((0x80000000
|0x00008000|0x00040000) & 0xf) == 0 || ((0x80000000|0x00008000
|0x00040000) & 0) == 1, "compile-time assertion failed")
3288 CTLFLAG_RD|CTLFLAG_CAPRD|CTLFLAG_MPSAFE, sysctl_kern_proc_nfds,struct sysctl_oid sysctl___kern_proc_nfds = { .oid_parent = (
(&(&sysctl___kern_proc)->oid_children)), .oid_children
= { ((void *)0) }, .oid_number = (43), .oid_kind = (1|(0x80000000
|0x00008000|0x00040000)), .oid_arg1 = (((void *)0)), .oid_arg2
= (0), .oid_name = ("nfds"), .oid_handler = (sysctl_kern_proc_nfds
), .oid_fmt = ("N"), .oid_descr = "Number of open file descriptors"
, .oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___kern_proc_nfds __attribute__
((__section__("set_" "sysctl_set"))) __attribute__((__used__)
) = &(sysctl___kern_proc_nfds); _Static_assert(((0x80000000
|0x00008000|0x00040000) & 0xf) == 0 || ((0x80000000|0x00008000
|0x00040000) & 0) == 1, "compile-time assertion failed")
3289 "Number of open file descriptors")struct sysctl_oid sysctl___kern_proc_nfds = { .oid_parent = (
(&(&sysctl___kern_proc)->oid_children)), .oid_children
= { ((void *)0) }, .oid_number = (43), .oid_kind = (1|(0x80000000
|0x00008000|0x00040000)), .oid_arg1 = (((void *)0)), .oid_arg2
= (0), .oid_name = ("nfds"), .oid_handler = (sysctl_kern_proc_nfds
), .oid_fmt = ("N"), .oid_descr = "Number of open file descriptors"
, .oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___kern_proc_nfds __attribute__
((__section__("set_" "sysctl_set"))) __attribute__((__used__)
) = &(sysctl___kern_proc_nfds); _Static_assert(((0x80000000
|0x00008000|0x00040000) & 0xf) == 0 || ((0x80000000|0x00008000
|0x00040000) & 0) == 1, "compile-time assertion failed")
;
3290
3291/*
3292 * Get file structures globally.
3293 */
3294static int
3295sysctl_kern_file(SYSCTL_HANDLER_ARGSstruct sysctl_oid *oidp, void *arg1, intmax_t arg2, struct sysctl_req
*req
)
3296{
3297 struct xfile xf;
3298 struct filedesc *fdp;
3299 struct file *fp;
3300 struct proc *p;
3301 int error, n;
3302
3303 error = sysctl_wire_old_buffer(req, 0);
3304 if (error != 0)
3305 return (error);
3306 if (req->oldptr == NULL((void *)0)) {
3307 n = 0;
3308 sx_slock(&allproc_lock)(void)_sx_slock(((&allproc_lock)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (3308))
;
3309 FOREACH_PROC_IN_SYSTEM(p)for (((p)) = (((&allproc))->lh_first); ((p)); ((p)) = (
(((p)))->p_list.le_next))
{
3310 PROC_LOCK(p)__mtx_lock_flags(&((((&(p)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (3310))
;
3311 if (p->p_state == PRS_NEW) {
3312 PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (3312))
;
3313 continue;
3314 }
3315 fdp = fdhold(p);
3316 PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (3316))
;
3317 if (fdp == NULL((void *)0))
3318 continue;
3319 /* overestimates sparse tables. */
3320 if (fdp->fd_lastfile > 0)
3321 n += fdp->fd_lastfile;
3322 fddrop(fdp);
3323 }
3324 sx_sunlock(&allproc_lock)_sx_sunlock(((&allproc_lock)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3324))
;
3325 return (SYSCTL_OUT(req, 0, n * sizeof(xf))(req->oldfunc)(req, 0, n * sizeof(xf)));
3326 }
3327 error = 0;
3328 bzero(&xf, sizeof(xf))__builtin_memset((&xf), 0, (sizeof(xf)));
3329 xf.xf_size = sizeof(xf);
3330 sx_slock(&allproc_lock)(void)_sx_slock(((&allproc_lock)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (3330))
;
3331 FOREACH_PROC_IN_SYSTEM(p)for (((p)) = (((&allproc))->lh_first); ((p)); ((p)) = (
(((p)))->p_list.le_next))
{
3332 PROC_LOCK(p)__mtx_lock_flags(&((((&(p)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (3332))
;
3333 if (p->p_state == PRS_NEW) {
3334 PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (3334))
;
3335 continue;
3336 }
3337 if (p_cansee(req->td, p) != 0) {
3338 PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (3338))
;
3339 continue;
3340 }
3341 xf.xf_pid = p->p_pid;
3342 xf.xf_uid = p->p_ucred->cr_uid;
3343 fdp = fdhold(p);
3344 PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (3344))
;
3345 if (fdp == NULL((void *)0))
3346 continue;
3347 FILEDESC_SLOCK(fdp)(void)_sx_slock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (3347))
;
3348 for (n = 0; fdp->fd_refcnt > 0 && n <= fdp->fd_lastfile; ++n) {
3349 if ((fp = fdp->fd_ofilesfd_files->fdt_ofiles[n].fde_file) == NULL((void *)0))
3350 continue;
3351 xf.xf_fd = n;
3352 xf.xf_file = (uintptr_t)fp;
3353 xf.xf_data = (uintptr_t)fp->f_data;
3354 xf.xf_vnode = (uintptr_t)fp->f_vnode;
3355 xf.xf_type = (uintptr_t)fp->f_type;
3356 xf.xf_count = fp->f_count;
3357 xf.xf_msgcount = 0;
3358 xf.xf_offset = foffset_get(fp);
3359 xf.xf_flag = fp->f_flag;
3360 error = SYSCTL_OUT(req, &xf, sizeof(xf))(req->oldfunc)(req, &xf, sizeof(xf));
3361 if (error)
3362 break;
3363 }
3364 FILEDESC_SUNLOCK(fdp)_sx_sunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3364))
;
3365 fddrop(fdp);
3366 if (error)
3367 break;
3368 }
3369 sx_sunlock(&allproc_lock)_sx_sunlock(((&allproc_lock)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3369))
;
3370 return (error);
3371}
3372
3373SYSCTL_PROC(_kern, KERN_FILE, file, CTLTYPE_OPAQUE|CTLFLAG_RD|CTLFLAG_MPSAFE,static struct sysctl_oid sysctl___kern_file = { .oid_parent =
((&(&sysctl___kern)->oid_children)), .oid_children
= { ((void *)0) }, .oid_number = (15), .oid_kind = ((5|0x80000000
|0x00040000)), .oid_arg1 = (0), .oid_arg2 = (0), .oid_name = (
"file"), .oid_handler = (sysctl_kern_file), .oid_fmt = ("S,xfile"
), .oid_descr = "Entire file table", .oid_label = (((void *)0
)), }; __asm__(".globl " "__start_set_sysctl_set"); __asm__(".globl "
"__stop_set_sysctl_set"); static void const * const __set_sysctl_set_sym_sysctl___kern_file
__attribute__((__section__("set_" "sysctl_set"))) __attribute__
((__used__)) = &(sysctl___kern_file); _Static_assert(((5|
0x80000000|0x00040000) & 0xf) != 0, "compile-time assertion failed"
)
3374 0, 0, sysctl_kern_file, "S,xfile", "Entire file table")static struct sysctl_oid sysctl___kern_file = { .oid_parent =
((&(&sysctl___kern)->oid_children)), .oid_children
= { ((void *)0) }, .oid_number = (15), .oid_kind = ((5|0x80000000
|0x00040000)), .oid_arg1 = (0), .oid_arg2 = (0), .oid_name = (
"file"), .oid_handler = (sysctl_kern_file), .oid_fmt = ("S,xfile"
), .oid_descr = "Entire file table", .oid_label = (((void *)0
)), }; __asm__(".globl " "__start_set_sysctl_set"); __asm__(".globl "
"__stop_set_sysctl_set"); static void const * const __set_sysctl_set_sym_sysctl___kern_file
__attribute__((__section__("set_" "sysctl_set"))) __attribute__
((__used__)) = &(sysctl___kern_file); _Static_assert(((5|
0x80000000|0x00040000) & 0xf) != 0, "compile-time assertion failed"
)
;
3375
3376#ifdef KINFO_FILE_SIZE1392
3377CTASSERT(sizeof(struct kinfo_file) == KINFO_FILE_SIZE)_Static_assert(sizeof(struct kinfo_file) == 1392, "compile-time assertion failed"
)
;
3378#endif
3379
3380static int
3381xlate_fflags(int fflags)
3382{
3383 static const struct {
3384 int fflag;
3385 int kf_fflag;
3386 } fflags_table[] = {
3387 { FAPPEND0x0008, KF_FLAG_APPEND0x00000004 },
3388 { FASYNC0x0040, KF_FLAG_ASYNC0x00000008 },
3389 { FFSYNC0x0080, KF_FLAG_FSYNC0x00000010 },
3390 { FHASLOCK0x4000, KF_FLAG_HASLOCK0x00000080 },
3391 { FNONBLOCK0x0004, KF_FLAG_NONBLOCK0x00000020 },
3392 { FREAD0x0001, KF_FLAG_READ0x00000001 },
3393 { FWRITE0x0002, KF_FLAG_WRITE0x00000002 },
3394 { O_CREAT0x0200, KF_FLAG_CREAT0x00000800 },
3395 { O_DIRECT0x00010000, KF_FLAG_DIRECT0x00000040 },
3396 { O_EXCL0x0800, KF_FLAG_EXCL0x00002000 },
3397 { O_EXEC0x00040000, KF_FLAG_EXEC0x00004000 },
3398 { O_EXLOCK0x0020, KF_FLAG_EXLOCK0x00000200 },
3399 { O_NOFOLLOW0x0100, KF_FLAG_NOFOLLOW0x00000400 },
3400 { O_SHLOCK0x0010, KF_FLAG_SHLOCK0x00000100 },
3401 { O_TRUNC0x0400, KF_FLAG_TRUNC0x00001000 }
3402 };
3403 unsigned int i;
3404 int kflags;
3405
3406 kflags = 0;
3407 for (i = 0; i < nitems(fflags_table)(sizeof((fflags_table)) / sizeof((fflags_table)[0])); i++)
3408 if (fflags & fflags_table[i].fflag)
3409 kflags |= fflags_table[i].kf_fflag;
3410 return (kflags);
3411}
3412
3413/* Trim unused data from kf_path by truncating the structure size. */
3414static void
3415pack_kinfo(struct kinfo_file *kif)
3416{
3417
3418 kif->kf_structsize = offsetof(struct kinfo_file, kf_path)__builtin_offsetof(struct kinfo_file, kf_path) +
3419 strlen(kif->kf_path) + 1;
3420 kif->kf_structsize = roundup(kif->kf_structsize, sizeof(uint64_t))((((kif->kf_structsize)+((sizeof(uint64_t))-1))/(sizeof(uint64_t
)))*(sizeof(uint64_t)))
;
3421}
3422
3423static void
3424export_file_to_kinfo(struct file *fp, int fd, cap_rights_t *rightsp,
3425 struct kinfo_file *kif, struct filedesc *fdp, int flags)
3426{
3427 int error;
3428
3429 bzero(kif, sizeof(*kif))__builtin_memset((kif), 0, (sizeof(*kif)));
3430
3431 /* Set a default type to allow for empty fill_kinfo() methods. */
3432 kif->kf_type = KF_TYPE_UNKNOWN255;
3433 kif->kf_flags = xlate_fflags(fp->f_flag);
3434 if (rightsp != NULL((void *)0))
3435 kif->kf_cap_rights = *rightsp;
3436 else
3437 cap_rights_init(&kif->kf_cap_rights)__cap_rights_init(0, &kif->kf_cap_rights, 0ULL);
3438 kif->kf_fd = fd;
3439 kif->kf_ref_count = fp->f_count;
3440 kif->kf_offset = foffset_get(fp);
3441
3442 /*
3443 * This may drop the filedesc lock, so the 'fp' cannot be
3444 * accessed after this call.
3445 */
3446 error = fo_fill_kinfo(fp, kif, fdp);
3447 if (error == 0)
3448 kif->kf_status |= KF_ATTR_VALID0x0001;
3449 if ((flags & KERN_FILEDESC_PACK_KINFO0x00000001U) != 0)
3450 pack_kinfo(kif);
3451 else
3452 kif->kf_structsize = roundup2(sizeof(*kif), sizeof(uint64_t))(((sizeof(*kif))+((sizeof(uint64_t))-1))&(~((sizeof(uint64_t
))-1)))
;
3453}
3454
3455static void
3456export_vnode_to_kinfo(struct vnode *vp, int fd, int fflags,
3457 struct kinfo_file *kif, int flags)
3458{
3459 int error;
3460
3461 bzero(kif, sizeof(*kif))__builtin_memset((kif), 0, (sizeof(*kif)));
3462
3463 kif->kf_type = KF_TYPE_VNODE1;
3464 error = vn_fill_kinfo_vnode(vp, kif);
3465 if (error == 0)
3466 kif->kf_status |= KF_ATTR_VALID0x0001;
3467 kif->kf_flags = xlate_fflags(fflags);
3468 cap_rights_init(&kif->kf_cap_rights)__cap_rights_init(0, &kif->kf_cap_rights, 0ULL);
3469 kif->kf_fd = fd;
3470 kif->kf_ref_count = -1;
3471 kif->kf_offset = -1;
3472 if ((flags & KERN_FILEDESC_PACK_KINFO0x00000001U) != 0)
3473 pack_kinfo(kif);
3474 else
3475 kif->kf_structsize = roundup2(sizeof(*kif), sizeof(uint64_t))(((sizeof(*kif))+((sizeof(uint64_t))-1))&(~((sizeof(uint64_t
))-1)))
;
3476 vrele(vp);
3477}
3478
3479struct export_fd_buf {
3480 struct filedesc *fdp;
3481 struct sbuf *sb;
3482 ssize_t remainder;
3483 struct kinfo_file kif;
3484 int flags;
3485};
3486
3487static int
3488export_kinfo_to_sb(struct export_fd_buf *efbuf)
3489{
3490 struct kinfo_file *kif;
3491
3492 kif = &efbuf->kif;
3493 if (efbuf->remainder != -1) {
3494 if (efbuf->remainder < kif->kf_structsize) {
3495 /* Terminate export. */
3496 efbuf->remainder = 0;
3497 return (0);
3498 }
3499 efbuf->remainder -= kif->kf_structsize;
3500 }
3501 return (sbuf_bcat(efbuf->sb, kif, kif->kf_structsize) == 0 ? 0 : ENOMEM12);
3502}
3503
3504static int
3505export_file_to_sb(struct file *fp, int fd, cap_rights_t *rightsp,
3506 struct export_fd_buf *efbuf)
3507{
3508 int error;
3509
3510 if (efbuf->remainder == 0)
3511 return (0);
3512 export_file_to_kinfo(fp, fd, rightsp, &efbuf->kif, efbuf->fdp,
3513 efbuf->flags);
3514 FILEDESC_SUNLOCK(efbuf->fdp)_sx_sunlock(((&(efbuf->fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3514))
;
3515 error = export_kinfo_to_sb(efbuf);
3516 FILEDESC_SLOCK(efbuf->fdp)(void)_sx_slock(((&(efbuf->fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (3516))
;
3517 return (error);
3518}
3519
3520static int
3521export_vnode_to_sb(struct vnode *vp, int fd, int fflags,
3522 struct export_fd_buf *efbuf)
3523{
3524 int error;
3525
3526 if (efbuf->remainder == 0)
3527 return (0);
3528 if (efbuf->fdp != NULL((void *)0))
3529 FILEDESC_SUNLOCK(efbuf->fdp)_sx_sunlock(((&(efbuf->fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3529))
;
3530 export_vnode_to_kinfo(vp, fd, fflags, &efbuf->kif, efbuf->flags);
3531 error = export_kinfo_to_sb(efbuf);
3532 if (efbuf->fdp != NULL((void *)0))
3533 FILEDESC_SLOCK(efbuf->fdp)(void)_sx_slock(((&(efbuf->fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (3533))
;
3534 return (error);
3535}
3536
3537/*
3538 * Store a process file descriptor information to sbuf.
3539 *
3540 * Takes a locked proc as argument, and returns with the proc unlocked.
3541 */
3542int
3543kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen,
3544 int flags)
3545{
3546 struct file *fp;
3547 struct filedesc *fdp;
3548 struct export_fd_buf *efbuf;
3549 struct vnode *cttyvp, *textvp, *tracevp;
3550 int error, i;
3551 cap_rights_t rights;
3552
3553 PROC_LOCK_ASSERT(p, MA_OWNED)__mtx_assert(&(((&(p)->p_mtx)))->mtx_lock, (((0x00000004
))), ("/root/freebsd/sys/kern/kern_descrip.c"), (3553))
;
3554
3555 /* ktrace vnode */
3556 tracevp = p->p_tracevp;
3557 if (tracevp != NULL((void *)0))
3558 vrefact(tracevp);
3559 /* text vnode */
3560 textvp = p->p_textvp;
3561 if (textvp != NULL((void *)0))
3562 vrefact(textvp);
3563 /* Controlling tty. */
3564 cttyvp = NULL((void *)0);
3565 if (p->p_pgrp != NULL((void *)0) && p->p_pgrp->pg_session != NULL((void *)0)) {
3566 cttyvp = p->p_pgrp->pg_session->s_ttyvp;
3567 if (cttyvp != NULL((void *)0))
3568 vrefact(cttyvp);
3569 }
3570 fdp = fdhold(p);
3571 PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (3571))
;
3572 efbuf = malloc(sizeof(*efbuf), M_TEMP, M_WAITOK0x0002);
3573 efbuf->fdp = NULL((void *)0);
3574 efbuf->sb = sb;
3575 efbuf->remainder = maxlen;
3576 efbuf->flags = flags;
3577 if (tracevp != NULL((void *)0))
3578 export_vnode_to_sb(tracevp, KF_FD_TYPE_TRACE-4, FREAD0x0001 | FWRITE0x0002,
3579 efbuf);
3580 if (textvp != NULL((void *)0))
3581 export_vnode_to_sb(textvp, KF_FD_TYPE_TEXT-5, FREAD0x0001, efbuf);
3582 if (cttyvp != NULL((void *)0))
3583 export_vnode_to_sb(cttyvp, KF_FD_TYPE_CTTY-6, FREAD0x0001 | FWRITE0x0002,
3584 efbuf);
3585 error = 0;
3586 if (fdp == NULL((void *)0))
3587 goto fail;
3588 efbuf->fdp = fdp;
3589 FILEDESC_SLOCK(fdp)(void)_sx_slock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (3589))
;
3590 /* working directory */
3591 if (fdp->fd_cdir != NULL((void *)0)) {
3592 vrefact(fdp->fd_cdir);
3593 export_vnode_to_sb(fdp->fd_cdir, KF_FD_TYPE_CWD-1, FREAD0x0001, efbuf);
3594 }
3595 /* root directory */
3596 if (fdp->fd_rdir != NULL((void *)0)) {
3597 vrefact(fdp->fd_rdir);
3598 export_vnode_to_sb(fdp->fd_rdir, KF_FD_TYPE_ROOT-2, FREAD0x0001, efbuf);
3599 }
3600 /* jail directory */
3601 if (fdp->fd_jdir != NULL((void *)0)) {
3602 vrefact(fdp->fd_jdir);
3603 export_vnode_to_sb(fdp->fd_jdir, KF_FD_TYPE_JAIL-3, FREAD0x0001, efbuf);
3604 }
3605 for (i = 0; fdp->fd_refcnt > 0 && i <= fdp->fd_lastfile; i++) {
3606 if ((fp = fdp->fd_ofilesfd_files->fdt_ofiles[i].fde_file) == NULL((void *)0))
3607 continue;
3608#ifdef CAPABILITIES1
3609 rights = *cap_rights(fdp, i);
3610#else /* !CAPABILITIES */
3611 rights = cap_no_rights;
3612#endif
3613 /*
3614 * Create sysctl entry. It is OK to drop the filedesc
3615 * lock inside of export_file_to_sb() as we will
3616 * re-validate and re-evaluate its properties when the
3617 * loop continues.
3618 */
3619 error = export_file_to_sb(fp, i, &rights, efbuf);
3620 if (error != 0 || efbuf->remainder == 0)
3621 break;
3622 }
3623 FILEDESC_SUNLOCK(fdp)_sx_sunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3623))
;
3624 fddrop(fdp);
3625fail:
3626 free(efbuf, M_TEMP);
3627 return (error);
3628}
3629
3630#define FILEDESC_SBUF_SIZE(sizeof(struct kinfo_file) * 5) (sizeof(struct kinfo_file) * 5)
3631
3632/*
3633 * Get per-process file descriptors for use by procstat(1), et al.
3634 */
3635static int
3636sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGSstruct sysctl_oid *oidp, void *arg1, intmax_t arg2, struct sysctl_req
*req
)
3637{
3638 struct sbuf sb;
3639 struct proc *p;
3640 ssize_t maxlen;
3641 int error, error2, *name;
3642
3643 name = (int *)arg1;
3644
3645 sbuf_new_for_sysctl(&sb, NULL((void *)0), FILEDESC_SBUF_SIZE(sizeof(struct kinfo_file) * 5), req);
3646 sbuf_clear_flags(&sb, SBUF_INCLUDENUL0x00000002);
3647 error = pget((pid_t)name[0], PGET_CANDEBUG0x00004 | PGET_NOTWEXIT0x00010, &p);
3648 if (error != 0) {
3649 sbuf_delete(&sb);
3650 return (error);
3651 }
3652 maxlen = req->oldptr != NULL((void *)0) ? req->oldlen : -1;
3653 error = kern_proc_filedesc_out(p, &sb, maxlen,
3654 KERN_FILEDESC_PACK_KINFO0x00000001U);
3655 error2 = sbuf_finish(&sb);
3656 sbuf_delete(&sb);
3657 return (error != 0 ? error : error2);
3658}
3659
3660#ifdef COMPAT_FREEBSD71
3661#ifdef KINFO_OFILE_SIZE1328
3662CTASSERT(sizeof(struct kinfo_ofile) == KINFO_OFILE_SIZE)_Static_assert(sizeof(struct kinfo_ofile) == 1328, "compile-time assertion failed"
)
;
3663#endif
3664
3665static void
3666kinfo_to_okinfo(struct kinfo_file *kif, struct kinfo_ofile *okif)
3667{
3668
3669 okif->kf_structsize = sizeof(*okif);
3670 okif->kf_type = kif->kf_type;
3671 okif->kf_fd = kif->kf_fd;
3672 okif->kf_ref_count = kif->kf_ref_count;
3673 okif->kf_flags = kif->kf_flags & (KF_FLAG_READ0x00000001 | KF_FLAG_WRITE0x00000002 |
3674 KF_FLAG_APPEND0x00000004 | KF_FLAG_ASYNC0x00000008 | KF_FLAG_FSYNC0x00000010 | KF_FLAG_NONBLOCK0x00000020 |
3675 KF_FLAG_DIRECT0x00000040 | KF_FLAG_HASLOCK0x00000080);
3676 okif->kf_offset = kif->kf_offset;
3677 if (kif->kf_type == KF_TYPE_VNODE1)
3678 okif->kf_vnode_type = kif->kf_un.kf_file.kf_file_type;
3679 else
3680 okif->kf_vnode_type = KF_VTYPE_VNON0;
3681 strlcpy(okif->kf_path, kif->kf_path, sizeof(okif->kf_path));
3682 if (kif->kf_type == KF_TYPE_SOCKET2) {
3683 okif->kf_sock_domain = kif->kf_un.kf_sock.kf_sock_domain0;
3684 okif->kf_sock_type = kif->kf_un.kf_sock.kf_sock_type0;
3685 okif->kf_sock_protocol = kif->kf_un.kf_sock.kf_sock_protocol0;
3686 okif->kf_sa_local = kif->kf_un.kf_sock.kf_sa_local;
3687 okif->kf_sa_peer = kif->kf_un.kf_sock.kf_sa_peer;
3688 } else {
3689 okif->kf_sa_local.ss_family = AF_UNSPEC0;
3690 okif->kf_sa_peer.ss_family = AF_UNSPEC0;
3691 }
3692}
3693
3694static int
3695export_vnode_for_osysctl(struct vnode *vp, int type, struct kinfo_file *kif,
3696 struct kinfo_ofile *okif, struct filedesc *fdp, struct sysctl_req *req)
3697{
3698 int error;
3699
3700 vrefact(vp);
3701 FILEDESC_SUNLOCK(fdp)_sx_sunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3701))
;
3702 export_vnode_to_kinfo(vp, type, 0, kif, KERN_FILEDESC_PACK_KINFO0x00000001U);
3703 kinfo_to_okinfo(kif, okif);
3704 error = SYSCTL_OUT(req, okif, sizeof(*okif))(req->oldfunc)(req, okif, sizeof(*okif));
3705 FILEDESC_SLOCK(fdp)(void)_sx_slock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (3705))
;
3706 return (error);
3707}
3708
3709/*
3710 * Get per-process file descriptors for use by procstat(1), et al.
3711 */
3712static int
3713sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGSstruct sysctl_oid *oidp, void *arg1, intmax_t arg2, struct sysctl_req
*req
)
3714{
3715 struct kinfo_ofile *okif;
3716 struct kinfo_file *kif;
3717 struct filedesc *fdp;
3718 int error, i, *name;
3719 struct file *fp;
3720 struct proc *p;
3721
3722 name = (int *)arg1;
3723 error = pget((pid_t)name[0], PGET_CANDEBUG0x00004 | PGET_NOTWEXIT0x00010, &p);
3724 if (error != 0)
3725 return (error);
3726 fdp = fdhold(p);
3727 PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (3727))
;
3728 if (fdp == NULL((void *)0))
3729 return (ENOENT2);
3730 kif = malloc(sizeof(*kif), M_TEMP, M_WAITOK0x0002);
3731 okif = malloc(sizeof(*okif), M_TEMP, M_WAITOK0x0002);
3732 FILEDESC_SLOCK(fdp)(void)_sx_slock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (3732))
;
3733 if (fdp->fd_cdir != NULL((void *)0))
3734 export_vnode_for_osysctl(fdp->fd_cdir, KF_FD_TYPE_CWD-1, kif,
3735 okif, fdp, req);
3736 if (fdp->fd_rdir != NULL((void *)0))
3737 export_vnode_for_osysctl(fdp->fd_rdir, KF_FD_TYPE_ROOT-2, kif,
3738 okif, fdp, req);
3739 if (fdp->fd_jdir != NULL((void *)0))
3740 export_vnode_for_osysctl(fdp->fd_jdir, KF_FD_TYPE_JAIL-3, kif,
3741 okif, fdp, req);
3742 for (i = 0; fdp->fd_refcnt > 0 && i <= fdp->fd_lastfile; i++) {
3743 if ((fp = fdp->fd_ofilesfd_files->fdt_ofiles[i].fde_file) == NULL((void *)0))
3744 continue;
3745 export_file_to_kinfo(fp, i, NULL((void *)0), kif, fdp,
3746 KERN_FILEDESC_PACK_KINFO0x00000001U);
3747 FILEDESC_SUNLOCK(fdp)_sx_sunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3747))
;
3748 kinfo_to_okinfo(kif, okif);
3749 error = SYSCTL_OUT(req, okif, sizeof(*okif))(req->oldfunc)(req, okif, sizeof(*okif));
3750 FILEDESC_SLOCK(fdp)(void)_sx_slock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (3750))
;
3751 if (error)
3752 break;
3753 }
3754 FILEDESC_SUNLOCK(fdp)_sx_sunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3754))
;
3755 fddrop(fdp);
3756 free(kif, M_TEMP);
3757 free(okif, M_TEMP);
3758 return (0);
3759}
3760
3761static SYSCTL_NODE(_kern_proc, KERN_PROC_OFILEDESC, ofiledesc,struct sysctl_oid sysctl___kern_proc_ofiledesc = { .oid_parent
= ((&(&sysctl___kern_proc)->oid_children)), .oid_children
= { ((void *)0) }, .oid_number = (14), .oid_kind = (1|(0x80000000
|0x00040000)), .oid_arg1 = (((void *)0)), .oid_arg2 = (0), .oid_name
= ("ofiledesc"), .oid_handler = (sysctl_kern_proc_ofiledesc)
, .oid_fmt = ("N"), .oid_descr = "Process ofiledesc entries",
.oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___kern_proc_ofiledesc __attribute__
((__section__("set_" "sysctl_set"))) __attribute__((__used__)
) = &(sysctl___kern_proc_ofiledesc); _Static_assert(((0x80000000
|0x00040000) & 0xf) == 0 || ((0x80000000|0x00040000) &
0) == 1, "compile-time assertion failed")
3762 CTLFLAG_RD|CTLFLAG_MPSAFE, sysctl_kern_proc_ofiledesc,struct sysctl_oid sysctl___kern_proc_ofiledesc = { .oid_parent
= ((&(&sysctl___kern_proc)->oid_children)), .oid_children
= { ((void *)0) }, .oid_number = (14), .oid_kind = (1|(0x80000000
|0x00040000)), .oid_arg1 = (((void *)0)), .oid_arg2 = (0), .oid_name
= ("ofiledesc"), .oid_handler = (sysctl_kern_proc_ofiledesc)
, .oid_fmt = ("N"), .oid_descr = "Process ofiledesc entries",
.oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___kern_proc_ofiledesc __attribute__
((__section__("set_" "sysctl_set"))) __attribute__((__used__)
) = &(sysctl___kern_proc_ofiledesc); _Static_assert(((0x80000000
|0x00040000) & 0xf) == 0 || ((0x80000000|0x00040000) &
0) == 1, "compile-time assertion failed")
3763 "Process ofiledesc entries")struct sysctl_oid sysctl___kern_proc_ofiledesc = { .oid_parent
= ((&(&sysctl___kern_proc)->oid_children)), .oid_children
= { ((void *)0) }, .oid_number = (14), .oid_kind = (1|(0x80000000
|0x00040000)), .oid_arg1 = (((void *)0)), .oid_arg2 = (0), .oid_name
= ("ofiledesc"), .oid_handler = (sysctl_kern_proc_ofiledesc)
, .oid_fmt = ("N"), .oid_descr = "Process ofiledesc entries",
.oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___kern_proc_ofiledesc __attribute__
((__section__("set_" "sysctl_set"))) __attribute__((__used__)
) = &(sysctl___kern_proc_ofiledesc); _Static_assert(((0x80000000
|0x00040000) & 0xf) == 0 || ((0x80000000|0x00040000) &
0) == 1, "compile-time assertion failed")
;
3764#endif /* COMPAT_FREEBSD7 */
3765
3766int
3767vntype_to_kinfo(int vtype)
3768{
3769 struct {
3770 int vtype;
3771 int kf_vtype;
3772 } vtypes_table[] = {
3773 { VBAD, KF_VTYPE_VBAD8 },
3774 { VBLK, KF_VTYPE_VBLK3 },
3775 { VCHR, KF_VTYPE_VCHR4 },
3776 { VDIR, KF_VTYPE_VDIR2 },
3777 { VFIFO, KF_VTYPE_VFIFO7 },
3778 { VLNK, KF_VTYPE_VLNK5 },
3779 { VNON, KF_VTYPE_VNON0 },
3780 { VREG, KF_VTYPE_VREG1 },
3781 { VSOCK, KF_VTYPE_VSOCK6 }
3782 };
3783 unsigned int i;
3784
3785 /*
3786 * Perform vtype translation.
3787 */
3788 for (i = 0; i < nitems(vtypes_table)(sizeof((vtypes_table)) / sizeof((vtypes_table)[0])); i++)
3789 if (vtypes_table[i].vtype == vtype)
3790 return (vtypes_table[i].kf_vtype);
3791
3792 return (KF_VTYPE_UNKNOWN255);
3793}
3794
3795static SYSCTL_NODE(_kern_proc, KERN_PROC_FILEDESC, filedesc,struct sysctl_oid sysctl___kern_proc_filedesc = { .oid_parent
= ((&(&sysctl___kern_proc)->oid_children)), .oid_children
= { ((void *)0) }, .oid_number = (33), .oid_kind = (1|(0x80000000
|0x00040000)), .oid_arg1 = (((void *)0)), .oid_arg2 = (0), .oid_name
= ("filedesc"), .oid_handler = (sysctl_kern_proc_filedesc), .
oid_fmt = ("N"), .oid_descr = "Process filedesc entries", .oid_label
= (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___kern_proc_filedesc __attribute__
((__section__("set_" "sysctl_set"))) __attribute__((__used__)
) = &(sysctl___kern_proc_filedesc); _Static_assert(((0x80000000
|0x00040000) & 0xf) == 0 || ((0x80000000|0x00040000) &
0) == 1, "compile-time assertion failed")
3796 CTLFLAG_RD|CTLFLAG_MPSAFE, sysctl_kern_proc_filedesc,struct sysctl_oid sysctl___kern_proc_filedesc = { .oid_parent
= ((&(&sysctl___kern_proc)->oid_children)), .oid_children
= { ((void *)0) }, .oid_number = (33), .oid_kind = (1|(0x80000000
|0x00040000)), .oid_arg1 = (((void *)0)), .oid_arg2 = (0), .oid_name
= ("filedesc"), .oid_handler = (sysctl_kern_proc_filedesc), .
oid_fmt = ("N"), .oid_descr = "Process filedesc entries", .oid_label
= (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___kern_proc_filedesc __attribute__
((__section__("set_" "sysctl_set"))) __attribute__((__used__)
) = &(sysctl___kern_proc_filedesc); _Static_assert(((0x80000000
|0x00040000) & 0xf) == 0 || ((0x80000000|0x00040000) &
0) == 1, "compile-time assertion failed")
3797 "Process filedesc entries")struct sysctl_oid sysctl___kern_proc_filedesc = { .oid_parent
= ((&(&sysctl___kern_proc)->oid_children)), .oid_children
= { ((void *)0) }, .oid_number = (33), .oid_kind = (1|(0x80000000
|0x00040000)), .oid_arg1 = (((void *)0)), .oid_arg2 = (0), .oid_name
= ("filedesc"), .oid_handler = (sysctl_kern_proc_filedesc), .
oid_fmt = ("N"), .oid_descr = "Process filedesc entries", .oid_label
= (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___kern_proc_filedesc __attribute__
((__section__("set_" "sysctl_set"))) __attribute__((__used__)
) = &(sysctl___kern_proc_filedesc); _Static_assert(((0x80000000
|0x00040000) & 0xf) == 0 || ((0x80000000|0x00040000) &
0) == 1, "compile-time assertion failed")
;
3798
3799/*
3800 * Store a process current working directory information to sbuf.
3801 *
3802 * Takes a locked proc as argument, and returns with the proc unlocked.
3803 */
3804int
3805kern_proc_cwd_out(struct proc *p, struct sbuf *sb, ssize_t maxlen)
3806{
3807 struct filedesc *fdp;
3808 struct export_fd_buf *efbuf;
3809 int error;
3810
3811 PROC_LOCK_ASSERT(p, MA_OWNED)__mtx_assert(&(((&(p)->p_mtx)))->mtx_lock, (((0x00000004
))), ("/root/freebsd/sys/kern/kern_descrip.c"), (3811))
;
3812
3813 fdp = fdhold(p);
3814 PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/kern_descrip.c"), (3814))
;
3815 if (fdp == NULL((void *)0))
3816 return (EINVAL22);
3817
3818 efbuf = malloc(sizeof(*efbuf), M_TEMP, M_WAITOK0x0002);
3819 efbuf->fdp = fdp;
3820 efbuf->sb = sb;
3821 efbuf->remainder = maxlen;
3822
3823 FILEDESC_SLOCK(fdp)(void)_sx_slock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/kern_descrip.c"
), (3823))
;
3824 if (fdp->fd_cdir == NULL((void *)0))
3825 error = EINVAL22;
3826 else {
3827 vrefact(fdp->fd_cdir);
3828 error = export_vnode_to_sb(fdp->fd_cdir, KF_FD_TYPE_CWD-1,
3829 FREAD0x0001, efbuf);
3830 }
3831 FILEDESC_SUNLOCK(fdp)_sx_sunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/kern_descrip.c"
), (3831))
;
3832 fddrop(fdp);
3833 free(efbuf, M_TEMP);
3834 return (error);
3835}
3836
3837/*
3838 * Get per-process current working directory.
3839 */
3840static int
3841sysctl_kern_proc_cwd(SYSCTL_HANDLER_ARGSstruct sysctl_oid *oidp, void *arg1, intmax_t arg2, struct sysctl_req
*req
)
3842{
3843 struct sbuf sb;
3844 struct proc *p;
3845 ssize_t maxlen;
3846 int error, error2, *name;
3847
3848 name = (int *)arg1;
3849
3850 sbuf_new_for_sysctl(&sb, NULL((void *)0), sizeof(struct kinfo_file), req);
3851 sbuf_clear_flags(&sb, SBUF_INCLUDENUL0x00000002);
3852 error = pget((pid_t)name[0], PGET_CANDEBUG0x00004 | PGET_NOTWEXIT0x00010, &p);
3853 if (error != 0) {
3854 sbuf_delete(&sb);
3855 return (error);
3856 }
3857 maxlen = req->oldptr != NULL((void *)0) ? req->oldlen : -1;
3858 error = kern_proc_cwd_out(p, &sb, maxlen);
3859 error2 = sbuf_finish(&sb);
3860 sbuf_delete(&sb);
3861 return (error != 0 ? error : error2);
3862}
3863
3864static SYSCTL_NODE(_kern_proc, KERN_PROC_CWD, cwd, CTLFLAG_RD|CTLFLAG_MPSAFE,struct sysctl_oid sysctl___kern_proc_cwd = { .oid_parent = ((
&(&sysctl___kern_proc)->oid_children)), .oid_children
= { ((void *)0) }, .oid_number = (42), .oid_kind = (1|(0x80000000
|0x00040000)), .oid_arg1 = (((void *)0)), .oid_arg2 = (0), .oid_name
= ("cwd"), .oid_handler = (sysctl_kern_proc_cwd), .oid_fmt =
("N"), .oid_descr = "Process current working directory", .oid_label
= (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___kern_proc_cwd __attribute__
((__section__("set_" "sysctl_set"))) __attribute__((__used__)
) = &(sysctl___kern_proc_cwd); _Static_assert(((0x80000000
|0x00040000) & 0xf) == 0 || ((0x80000000|0x00040000) &
0) == 1, "compile-time assertion failed")
3865 sysctl_kern_proc_cwd, "Process current working directory")struct sysctl_oid sysctl___kern_proc_cwd = { .oid_parent = ((
&(&sysctl___kern_proc)->oid_children)), .oid_children
= { ((void *)0) }, .oid_number = (42), .oid_kind = (1|(0x80000000
|0x00040000)), .oid_arg1 = (((void *)0)), .oid_arg2 = (0), .oid_name
= ("cwd"), .oid_handler = (sysctl_kern_proc_cwd), .oid_fmt =
("N"), .oid_descr = "Process current working directory", .oid_label
= (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___kern_proc_cwd __attribute__
((__section__("set_" "sysctl_set"))) __attribute__((__used__)
) = &(sysctl___kern_proc_cwd); _Static_assert(((0x80000000
|0x00040000) & 0xf) == 0 || ((0x80000000|0x00040000) &
0) == 1, "compile-time assertion failed")
;
3866
3867#ifdef DDB1
3868/*
3869 * For the purposes of debugging, generate a human-readable string for the
3870 * file type.
3871 */
3872static const char *
3873file_type_to_name(short type)
3874{
3875
3876 switch (type) {
3877 case 0:
3878 return ("zero");
3879 case DTYPE_VNODE1:
3880 return ("vnode");
3881 case DTYPE_SOCKET2:
3882 return ("socket");
3883 case DTYPE_PIPE3:
3884 return ("pipe");
3885 case DTYPE_FIFO4:
3886 return ("fifo");
3887 case DTYPE_KQUEUE5:
3888 return ("kqueue");
3889 case DTYPE_CRYPTO6:
3890 return ("crypto");
3891 case DTYPE_MQUEUE7:
3892 return ("mqueue");
3893 case DTYPE_SHM8:
3894 return ("shm");
3895 case DTYPE_SEM9:
3896 return ("ksem");
3897 case DTYPE_PTS10:
3898 return ("pts");
3899 case DTYPE_DEV11:
3900 return ("dev");
3901 case DTYPE_PROCDESC12:
3902 return ("proc");
3903 case DTYPE_LINUXEFD13:
3904 return ("levent");
3905 case DTYPE_LINUXTFD14:
3906 return ("ltimer");
3907 default:
3908 return ("unkn");
3909 }
3910}
3911
3912/*
3913 * For the purposes of debugging, identify a process (if any, perhaps one of
3914 * many) that references the passed file in its file descriptor array. Return
3915 * NULL if none.
3916 */
3917static struct proc *
3918file_to_first_proc(struct file *fp)
3919{
3920 struct filedesc *fdp;
3921 struct proc *p;
3922 int n;
3923
3924 FOREACH_PROC_IN_SYSTEM(p)for (((p)) = (((&allproc))->lh_first); ((p)); ((p)) = (
(((p)))->p_list.le_next))
{
3925 if (p->p_state == PRS_NEW)
3926 continue;
3927 fdp = p->p_fd;
3928 if (fdp == NULL((void *)0))
3929 continue;
3930 for (n = 0; n <= fdp->fd_lastfile; n++) {
3931 if (fp == fdp->fd_ofilesfd_files->fdt_ofiles[n].fde_file)
3932 return (p);
3933 }
3934 }
3935 return (NULL((void *)0));
3936}
3937
3938static void
3939db_print_file(struct file *fp, int header)
3940{
3941#define XPTRWIDTH ((int)howmany(sizeof(void *) * NBBY, 4)(((sizeof(void *) * 8)+((4)-1))/(4)))
3942 struct proc *p;
3943
3944 if (header)
3945 db_printf("%*s %6s %*s %8s %4s %5s %6s %*s %5s %s\n",
3946 XPTRWIDTH, "File", "Type", XPTRWIDTH, "Data", "Flag",
3947 "GCFl", "Count", "MCount", XPTRWIDTH, "Vnode", "FPID",
3948 "FCmd");
3949 p = file_to_first_proc(fp);
3950 db_printf("%*p %6s %*p %08x %04x %5d %6d %*p %5d %s\n", XPTRWIDTH,
3951 fp, file_type_to_name(fp->f_type), XPTRWIDTH, fp->f_data,
3952 fp->f_flag, 0, fp->f_count, 0, XPTRWIDTH, fp->f_vnode,
3953 p != NULL((void *)0) ? p->p_pid : -1, p != NULL((void *)0) ? p->p_comm : "-");
3954
3955#undef XPTRWIDTH
3956}
3957
3958DB_SHOW_COMMAND(file, db_show_file)static db_cmdfcn_t db_show_file; static struct command file_show
= { .name = "file", .fcn = db_show_file, .flag = 0, .more = (
(void *)0) }; static void file_show_add(void *arg __attribute__
((__unused__))) { db_command_register(&db_show_table, &
file_show); } static struct sysinit file_show_sys_init = { SI_SUB_KLD
, SI_ORDER_ANY, (sysinit_cfunc_t)(sysinit_nfunc_t)file_show_add
, ((void *)(((void *)0))) }; __asm__(".globl " "__start_set_sysinit_set"
); __asm__(".globl " "__stop_set_sysinit_set"); static void const
* __set_sysinit_set_sym_file_show_sys_init __attribute__((__section__
("set_" "sysinit_set"))) __attribute__((__used__)) = &(file_show_sys_init
); static void file_show_del(void *arg __attribute__((__unused__
))) { db_command_unregister(&db_show_table, &file_show
); } static struct sysinit file_show_sys_uninit = { SI_SUB_KLD
, SI_ORDER_ANY, (sysinit_cfunc_t)(sysinit_nfunc_t)file_show_del
, ((void *)(((void *)0))) }; __asm__(".globl " "__start_set_sysuninit_set"
); __asm__(".globl " "__stop_set_sysuninit_set"); static void
const * __set_sysuninit_set_sym_file_show_sys_uninit __attribute__
((__section__("set_" "sysuninit_set"))) __attribute__((__used__
)) = &(file_show_sys_uninit);; static void db_show_file(db_expr_t
addr, bool have_addr, db_expr_t count, char *modif)
3959{
3960 struct file *fp;
3961
3962 if (!have_addr) {
3963 db_printf("usage: show file <addr>\n");
3964 return;
3965 }
3966 fp = (struct file *)addr;
3967 db_print_file(fp, 1);
3968}
3969
3970DB_SHOW_COMMAND(files, db_show_files)static db_cmdfcn_t db_show_files; static struct command files_show
= { .name = "files", .fcn = db_show_files, .flag = 0, .more =
((void *)0) }; static void files_show_add(void *arg __attribute__
((__unused__))) { db_command_register(&db_show_table, &
files_show); } static struct sysinit files_show_sys_init = { SI_SUB_KLD
, SI_ORDER_ANY, (sysinit_cfunc_t)(sysinit_nfunc_t)files_show_add
, ((void *)(((void *)0))) }; __asm__(".globl " "__start_set_sysinit_set"
); __asm__(".globl " "__stop_set_sysinit_set"); static void const
* __set_sysinit_set_sym_files_show_sys_init __attribute__((__section__
("set_" "sysinit_set"))) __attribute__((__used__)) = &(files_show_sys_init
); static void files_show_del(void *arg __attribute__((__unused__
))) { db_command_unregister(&db_show_table, &files_show
); } static struct sysinit files_show_sys_uninit = { SI_SUB_KLD
, SI_ORDER_ANY, (sysinit_cfunc_t)(sysinit_nfunc_t)files_show_del
, ((void *)(((void *)0))) }; __asm__(".globl " "__start_set_sysuninit_set"
); __asm__(".globl " "__stop_set_sysuninit_set"); static void
const * __set_sysuninit_set_sym_files_show_sys_uninit __attribute__
((__section__("set_" "sysuninit_set"))) __attribute__((__used__
)) = &(files_show_sys_uninit);; static void db_show_files
(db_expr_t addr, bool have_addr, db_expr_t count, char *modif
)
3971{
3972 struct filedesc *fdp;
3973 struct file *fp;
3974 struct proc *p;
3975 int header;
3976 int n;
3977
3978 header = 1;
3979 FOREACH_PROC_IN_SYSTEM(p)for (((p)) = (((&allproc))->lh_first); ((p)); ((p)) = (
(((p)))->p_list.le_next))
{
3980 if (p->p_state == PRS_NEW)
3981 continue;
3982 if ((fdp = p->p_fd) == NULL((void *)0))
3983 continue;
3984 for (n = 0; n <= fdp->fd_lastfile; ++n) {
3985 if ((fp = fdp->fd_ofilesfd_files->fdt_ofiles[n].fde_file) == NULL((void *)0))
3986 continue;
3987 db_print_file(fp, header);
3988 header = 0;
3989 }
3990 }
3991}
3992#endif
3993
3994SYSCTL_INT(_kern, KERN_MAXFILESPERPROC, maxfilesperproc, CTLFLAG_RW,static struct sysctl_oid sysctl___kern_maxfilesperproc = { .oid_parent
= ((&(&sysctl___kern)->oid_children)), .oid_children
= { ((void *)0) }, .oid_number = (27), .oid_kind = (2 | 0x00040000
| ((0x80000000|0x40000000))), .oid_arg1 = (&maxfilesperproc
), .oid_arg2 = (0), .oid_name = ("maxfilesperproc"), .oid_handler
= (sysctl_handle_int), .oid_fmt = ("I"), .oid_descr = "Maximum files allowed open per process"
, .oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___kern_maxfilesperproc __attribute__
((__section__("set_" "sysctl_set"))) __attribute__((__used__)
) = &(sysctl___kern_maxfilesperproc); _Static_assert(((((
0x80000000|0x40000000)) & 0xf) == 0 || (((0x80000000|0x40000000
)) & 0) == 2) && sizeof(int) == sizeof(*(&maxfilesperproc
)), "compile-time assertion failed")
3995 &maxfilesperproc, 0, "Maximum files allowed open per process")static struct sysctl_oid sysctl___kern_maxfilesperproc = { .oid_parent
= ((&(&sysctl___kern)->oid_children)), .oid_children
= { ((void *)0) }, .oid_number = (27), .oid_kind = (2 | 0x00040000
| ((0x80000000|0x40000000))), .oid_arg1 = (&maxfilesperproc
), .oid_arg2 = (0), .oid_name = ("maxfilesperproc"), .oid_handler
= (sysctl_handle_int), .oid_fmt = ("I"), .oid_descr = "Maximum files allowed open per process"
, .oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___kern_maxfilesperproc __attribute__
((__section__("set_" "sysctl_set"))) __attribute__((__used__)
) = &(sysctl___kern_maxfilesperproc); _Static_assert(((((
0x80000000|0x40000000)) & 0xf) == 0 || (((0x80000000|0x40000000
)) & 0) == 2) && sizeof(int) == sizeof(*(&maxfilesperproc
)), "compile-time assertion failed")
;
3996
3997SYSCTL_INT(_kern, KERN_MAXFILES, maxfiles, CTLFLAG_RW,static struct sysctl_oid sysctl___kern_maxfiles = { .oid_parent
= ((&(&sysctl___kern)->oid_children)), .oid_children
= { ((void *)0) }, .oid_number = (7), .oid_kind = (2 | 0x00040000
| ((0x80000000|0x40000000))), .oid_arg1 = (&maxfiles), .
oid_arg2 = (0), .oid_name = ("maxfiles"), .oid_handler = (sysctl_handle_int
), .oid_fmt = ("I"), .oid_descr = "Maximum number of files", .
oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___kern_maxfiles __attribute__
((__section__("set_" "sysctl_set"))) __attribute__((__used__)
) = &(sysctl___kern_maxfiles); _Static_assert(((((0x80000000
|0x40000000)) & 0xf) == 0 || (((0x80000000|0x40000000)) &
0) == 2) && sizeof(int) == sizeof(*(&maxfiles)),
"compile-time assertion failed")
3998 &maxfiles, 0, "Maximum number of files")static struct sysctl_oid sysctl___kern_maxfiles = { .oid_parent
= ((&(&sysctl___kern)->oid_children)), .oid_children
= { ((void *)0) }, .oid_number = (7), .oid_kind = (2 | 0x00040000
| ((0x80000000|0x40000000))), .oid_arg1 = (&maxfiles), .
oid_arg2 = (0), .oid_name = ("maxfiles"), .oid_handler = (sysctl_handle_int
), .oid_fmt = ("I"), .oid_descr = "Maximum number of files", .
oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___kern_maxfiles __attribute__
((__section__("set_" "sysctl_set"))) __attribute__((__used__)
) = &(sysctl___kern_maxfiles); _Static_assert(((((0x80000000
|0x40000000)) & 0xf) == 0 || (((0x80000000|0x40000000)) &
0) == 2) && sizeof(int) == sizeof(*(&maxfiles)),
"compile-time assertion failed")
;
3999
4000SYSCTL_INT(_kern, OID_AUTO, openfiles, CTLFLAG_RD,static struct sysctl_oid sysctl___kern_openfiles = { .oid_parent
= ((&(&sysctl___kern)->oid_children)), .oid_children
= { ((void *)0) }, .oid_number = ((-1)), .oid_kind = (2 | 0x00040000
| (0x80000000)), .oid_arg1 = (((int *)(__uintptr_t)(volatile
void *)(&openfiles))), .oid_arg2 = (0), .oid_name = ("openfiles"
), .oid_handler = (sysctl_handle_int), .oid_fmt = ("I"), .oid_descr
= "System-wide number of open files", .oid_label = (((void *
)0)), }; __asm__(".globl " "__start_set_sysctl_set"); __asm__
(".globl " "__stop_set_sysctl_set"); static void const * const
__set_sysctl_set_sym_sysctl___kern_openfiles __attribute__((
__section__("set_" "sysctl_set"))) __attribute__((__used__)) =
&(sysctl___kern_openfiles); _Static_assert((((0x80000000
) & 0xf) == 0 || ((0x80000000) & 0) == 2) && sizeof
(int) == sizeof(*(((int *)(__uintptr_t)(volatile void *)(&
openfiles)))), "compile-time assertion failed")
4001 __DEVOLATILE(int *, &openfiles), 0, "System-wide number of open files")static struct sysctl_oid sysctl___kern_openfiles = { .oid_parent
= ((&(&sysctl___kern)->oid_children)), .oid_children
= { ((void *)0) }, .oid_number = ((-1)), .oid_kind = (2 | 0x00040000
| (0x80000000)), .oid_arg1 = (((int *)(__uintptr_t)(volatile
void *)(&openfiles))), .oid_arg2 = (0), .oid_name = ("openfiles"
), .oid_handler = (sysctl_handle_int), .oid_fmt = ("I"), .oid_descr
= "System-wide number of open files", .oid_label = (((void *
)0)), }; __asm__(".globl " "__start_set_sysctl_set"); __asm__
(".globl " "__stop_set_sysctl_set"); static void const * const
__set_sysctl_set_sym_sysctl___kern_openfiles __attribute__((
__section__("set_" "sysctl_set"))) __attribute__((__used__)) =
&(sysctl___kern_openfiles); _Static_assert((((0x80000000
) & 0xf) == 0 || ((0x80000000) & 0) == 2) && sizeof
(int) == sizeof(*(((int *)(__uintptr_t)(volatile void *)(&
openfiles)))), "compile-time assertion failed")
;
4002
4003/* ARGSUSED*/
4004static void
4005filelistinit(void *dummy)
4006{
4007
4008 file_zone = uma_zcreate("Files", sizeof(struct file), NULL((void *)0), NULL((void *)0),
4009 NULL((void *)0), NULL((void *)0), UMA_ALIGN_PTR(sizeof(void *) - 1), UMA_ZONE_NOFREE0x0020);
4010 filedesc0_zone = uma_zcreate("filedesc0", sizeof(struct filedesc0),
4011 NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0), UMA_ALIGN_PTR(sizeof(void *) - 1), 0);
4012 mtx_init(&sigio_lock, "sigio lock", NULL, MTX_DEF)_mtx_init(&(&sigio_lock)->mtx_lock, "sigio lock", (
(void *)0), 0x00000000)
;
4013}
4014SYSINIT(select, SI_SUB_LOCK, SI_ORDER_FIRST, filelistinit, NULL)static struct sysinit select_sys_init = { SI_SUB_LOCK, SI_ORDER_FIRST
, (sysinit_cfunc_t)(sysinit_nfunc_t)filelistinit, ((void *)((
(void *)0))) }; __asm__(".globl " "__start_set_sysinit_set");
__asm__(".globl " "__stop_set_sysinit_set"); static void const
* __set_sysinit_set_sym_select_sys_init __attribute__((__section__
("set_" "sysinit_set"))) __attribute__((__used__)) = &(select_sys_init
)
;
4015
4016/*-------------------------------------------------------------------*/
4017
4018static int
4019badfo_readwrite(struct file *fp, struct uio *uio, struct ucred *active_cred,
4020 int flags, struct thread *td)
4021{
4022
4023 return (EBADF9);
4024}
4025
4026static int
4027badfo_truncate(struct file *fp, off_t length, struct ucred *active_cred,
4028 struct thread *td)
4029{
4030
4031 return (EINVAL22);
4032}
4033
4034static int
4035badfo_ioctl(struct file *fp, u_long com, void *data, struct ucred *active_cred,
4036 struct thread *td)
4037{
4038
4039 return (EBADF9);
4040}
4041
4042static int
4043badfo_poll(struct file *fp, int events, struct ucred *active_cred,
4044 struct thread *td)
4045{
4046
4047 return (0);
4048}
4049
4050static int
4051badfo_kqfilter(struct file *fp, struct knote *kn)
4052{
4053
4054 return (EBADF9);
4055}
4056
4057static int
4058badfo_stat(struct file *fp, struct stat *sb, struct ucred *active_cred,
4059 struct thread *td)
4060{
4061
4062 return (EBADF9);
4063}
4064
4065static int
4066badfo_close(struct file *fp, struct thread *td)
4067{
4068
4069 return (0);
4070}
4071
4072static int
4073badfo_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
4074 struct thread *td)
4075{
4076
4077 return (EBADF9);
4078}
4079
4080static int
4081badfo_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
4082 struct thread *td)
4083{
4084
4085 return (EBADF9);
4086}
4087
4088static int
4089badfo_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
4090 struct uio *trl_uio, off_t offset, size_t nbytes, off_t *sent, int flags,
4091 struct thread *td)
4092{
4093
4094 return (EBADF9);
4095}
4096
4097static int
4098badfo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
4099{
4100
4101 return (0);
4102}
4103
4104struct fileops badfileops = {
4105 .fo_read = badfo_readwrite,
4106 .fo_write = badfo_readwrite,
4107 .fo_truncate = badfo_truncate,
4108 .fo_ioctl = badfo_ioctl,
4109 .fo_poll = badfo_poll,
4110 .fo_kqfilter = badfo_kqfilter,
4111 .fo_stat = badfo_stat,
4112 .fo_close = badfo_close,
4113 .fo_chmod = badfo_chmod,
4114 .fo_chown = badfo_chown,
4115 .fo_sendfile = badfo_sendfile,
4116 .fo_fill_kinfo = badfo_fill_kinfo,
4117};
4118
4119int
4120invfo_rdwr(struct file *fp, struct uio *uio, struct ucred *active_cred,
4121 int flags, struct thread *td)
4122{
4123
4124 return (EOPNOTSUPP45);
4125}
4126
4127int
4128invfo_truncate(struct file *fp, off_t length, struct ucred *active_cred,
4129 struct thread *td)
4130{
4131
4132 return (EINVAL22);
4133}
4134
4135int
4136invfo_ioctl(struct file *fp, u_long com, void *data,
4137 struct ucred *active_cred, struct thread *td)
4138{
4139
4140 return (ENOTTY25);
4141}
4142
4143int
4144invfo_poll(struct file *fp, int events, struct ucred *active_cred,
4145 struct thread *td)
4146{
4147
4148 return (poll_no_poll(events));
4149}
4150
4151int
4152invfo_kqfilter(struct file *fp, struct knote *kn)
4153{
4154
4155 return (EINVAL22);
4156}
4157
4158int
4159invfo_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
4160 struct thread *td)
4161{
4162
4163 return (EINVAL22);
4164}
4165
4166int
4167invfo_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
4168 struct thread *td)
4169{
4170
4171 return (EINVAL22);
4172}
4173
4174int
4175invfo_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
4176 struct uio *trl_uio, off_t offset, size_t nbytes, off_t *sent, int flags,
4177 struct thread *td)
4178{
4179
4180 return (EINVAL22);
4181}
4182
4183/*-------------------------------------------------------------------*/
4184
4185/*
4186 * File Descriptor pseudo-device driver (/dev/fd/).
4187 *
4188 * Opening minor device N dup()s the file (if any) connected to file
4189 * descriptor N belonging to the calling process. Note that this driver
4190 * consists of only the ``open()'' routine, because all subsequent
4191 * references to this file will be direct to the other driver.
4192 *
4193 * XXX: we could give this one a cloning event handler if necessary.
4194 */
4195
4196/* ARGSUSED */
4197static int
4198fdopen(struct cdev *dev, int mode, int type, struct thread *td)
4199{
4200
4201 /*
4202 * XXX Kludge: set curthread->td_dupfd to contain the value of the
4203 * the file descriptor being sought for duplication. The error
4204 * return ensures that the vnode for this device will be released
4205 * by vn_open. Open will detect this special error and take the
4206 * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
4207 * will simply report the error.
4208 */
4209 td->td_dupfd = dev2unit(dev)((dev)->si_drv0);
4210 return (ENODEV19);
4211}
4212
4213static struct cdevsw fildesc_cdevsw = {
4214 .d_version = D_VERSION0x17122009,
4215 .d_open = fdopen,
4216 .d_name = "FD",
4217};
4218
4219static void
4220fildesc_drvinit(void *unused)
4221{
4222 struct cdev *dev;
4223
4224 dev = make_dev_credf(MAKEDEV_ETERNAL0x10, &fildesc_cdevsw, 0, NULL((void *)0),
4225 UID_ROOT0, GID_WHEEL0, 0666, "fd/0");
4226 make_dev_alias(dev, "stdin");
4227 dev = make_dev_credf(MAKEDEV_ETERNAL0x10, &fildesc_cdevsw, 1, NULL((void *)0),
4228 UID_ROOT0, GID_WHEEL0, 0666, "fd/1");
4229 make_dev_alias(dev, "stdout");
4230 dev = make_dev_credf(MAKEDEV_ETERNAL0x10, &fildesc_cdevsw, 2, NULL((void *)0),
4231 UID_ROOT0, GID_WHEEL0, 0666, "fd/2");
4232 make_dev_alias(dev, "stderr");
4233}
4234
4235SYSINIT(fildescdev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, fildesc_drvinit, NULL)static struct sysinit fildescdev_sys_init = { SI_SUB_DRIVERS,
SI_ORDER_MIDDLE, (sysinit_cfunc_t)(sysinit_nfunc_t)fildesc_drvinit
, ((void *)(((void *)0))) }; __asm__(".globl " "__start_set_sysinit_set"
); __asm__(".globl " "__stop_set_sysinit_set"); static void const
* __set_sysinit_set_sym_fildescdev_sys_init __attribute__((__section__
("set_" "sysinit_set"))) __attribute__((__used__)) = &(fildescdev_sys_init
)
;