master
  1/*-
  2 * SPDX-License-Identifier: BSD-3-Clause
  3 *
  4 * Copyright (c) 1990, 1993
  5 *	The Regents of the University of California.  All rights reserved.
  6 *
  7 * Redistribution and use in source and binary forms, with or without
  8 * modification, are permitted provided that the following conditions
  9 * are met:
 10 * 1. Redistributions of source code must retain the above copyright
 11 *    notice, this list of conditions and the following disclaimer.
 12 * 2. Redistributions in binary form must reproduce the above copyright
 13 *    notice, this list of conditions and the following disclaimer in the
 14 *    documentation and/or other materials provided with the distribution.
 15 * 3. Neither the name of the University nor the names of its contributors
 16 *    may be used to endorse or promote products derived from this software
 17 *    without specific prior written permission.
 18 *
 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 29 * SUCH DAMAGE.
 30 *
 31 *	@(#)filedesc.h	8.1 (Berkeley) 6/2/93
 32 */
 33
 34#ifndef _SYS_FILEDESC_H_
 35#define	_SYS_FILEDESC_H_
 36
 37#include <sys/types.h>
 38#include <sys/caprights.h>
 39#include <sys/queue.h>
 40#include <sys/event.h>
 41#include <sys/lock.h>
 42#include <sys/mutex.h>
 43#include <sys/priority.h>
 44#include <sys/seqc.h>
 45#include <sys/sx.h>
 46#include <sys/_smr.h>
 47#include <sys/smr_types.h>
 48
 49#include <machine/_limits.h>
 50
 51struct filecaps {
 52	cap_rights_t	 fc_rights;	/* per-descriptor capability rights */
 53	u_long		*fc_ioctls;	/* per-descriptor allowed ioctls */
 54	int16_t		 fc_nioctls;	/* fc_ioctls array size */
 55	uint32_t	 fc_fcntls;	/* per-descriptor allowed fcntls */
 56};
 57
 58struct filedescent {
 59	struct file	*fde_file;	/* file structure for open file */
 60	struct filecaps	 fde_caps;	/* per-descriptor rights */
 61	uint8_t		 fde_flags;	/* per-process open file flags */
 62	seqc_t		 fde_seqc;	/* keep file and caps in sync */
 63};
 64#define	fde_rights	fde_caps.fc_rights
 65#define	fde_fcntls	fde_caps.fc_fcntls
 66#define	fde_ioctls	fde_caps.fc_ioctls
 67#define	fde_nioctls	fde_caps.fc_nioctls
 68
 69#ifdef _KERNEL
 70static inline void
 71fde_copy(struct filedescent *from, struct filedescent *to)
 72{
 73
 74	to->fde_file = from->fde_file;
 75	to->fde_caps = from->fde_caps;
 76	to->fde_flags = from->fde_flags;
 77}
 78#endif
 79
 80struct fdescenttbl {
 81	int	fdt_nfiles;		/* number of open files allocated */
 82	struct	filedescent fdt_ofiles[0];	/* open files */
 83};
 84#define	fd_seqc(fdt, fd)	(&(fdt)->fdt_ofiles[(fd)].fde_seqc)
 85
 86#define NDSLOTTYPE	u_long
 87
 88/*
 89 * This struct is copy-on-write and allocated from an SMR zone.
 90 * All fields are constant after initialization apart from the reference count.
 91 * The ABI root directory is initialized as the root directory and changed
 92 * during process transiting to or from non-native ABI.
 93 *
 94 * Check pwd_* routines for usage.
 95 */
 96struct pwd {
 97	u_int		pwd_refcount;
 98	struct	vnode	*pwd_cdir;	/* current directory */
 99	struct	vnode	*pwd_rdir;	/* root directory */
100	struct	vnode	*pwd_jdir;	/* jail root directory */
101	struct	vnode	*pwd_adir;	/* abi root directory */
102};
103typedef SMR_POINTER(struct pwd *) smrpwd_t;
104
105struct pwddesc {
106	struct mtx	pd_lock;	/* protects members of this struct */
107	smrpwd_t	pd_pwd;		/* directories */
108	u_int		pd_refcount;
109	u_short		pd_cmask;	/* mask for file creation */
110};
111
112/*
113 * This structure is used for the management of descriptors.  It may be
114 * shared by multiple processes.
115 */
116struct filedesc {
117	struct	fdescenttbl *fd_files;	/* open files table */
118	NDSLOTTYPE *fd_map;		/* bitmap of free fds */
119	int	fd_freefile;		/* approx. next free file */
120	int	fd_refcnt;		/* thread reference count */
121	int	fd_holdcnt;		/* hold count on structure + mutex */
122	struct	sx fd_sx;		/* protects members of this struct */
123	struct	kqlist fd_kqlist;	/* list of kqueues on this filedesc */
124	int	fd_holdleaderscount;	/* block fdfree() for shared close() */
125	int	fd_holdleaderswakeup;	/* fdfree() needs wakeup */
126};
127
128/*
129 * Structure to keep track of (process leader, struct fildedesc) tuples.
130 * Each process has a pointer to such a structure when detailed tracking
131 * is needed, e.g., when rfork(RFPROC | RFMEM) causes a file descriptor
132 * table to be shared by processes having different "p_leader" pointers
133 * and thus distinct POSIX style locks.
134 *
135 * fdl_refcount and fdl_holdcount are protected by struct filedesc mtx.
136 */
137struct filedesc_to_leader {
138	int		fdl_refcount;	/* references from struct proc */
139	int		fdl_holdcount;	/* temporary hold during closef */
140	int		fdl_wakeup;	/* fdfree() waits on closef() */
141	struct proc	*fdl_leader;	/* owner of POSIX locks */
142	/* Circular list: */
143	struct filedesc_to_leader *fdl_prev;
144	struct filedesc_to_leader *fdl_next;
145};
146#define	fd_nfiles	fd_files->fdt_nfiles
147#define	fd_ofiles	fd_files->fdt_ofiles
148
149/*
150 * Per-process open flags.
151 */
152#define	UF_EXCLOSE	0x01		/* auto-close on exec */
153
154#ifdef _KERNEL
155
156/* Lock a paths descriptor table. */
157#define	PWDDESC_LOCK(pdp)	(&(pdp)->pd_lock)
158#define	PWDDESC_LOCK_INIT(pdp) \
159    mtx_init(PWDDESC_LOCK(pdp), "pwddesc", NULL, MTX_DEF)
160#define	PWDDESC_LOCK_DESTROY(pdp)	mtx_destroy(PWDDESC_LOCK(pdp))
161#define	PWDDESC_XLOCK(pdp)	mtx_lock(PWDDESC_LOCK(pdp))
162#define	PWDDESC_XUNLOCK(pdp)	mtx_unlock(PWDDESC_LOCK(pdp))
163#define	PWDDESC_LOCK_ASSERT(pdp, what) \
164    mtx_assert(PWDDESC_LOCK(pdp), (what))
165#define	PWDDESC_ASSERT_XLOCKED(pdp) \
166    PWDDESC_LOCK_ASSERT((pdp), MA_OWNED)
167#define	PWDDESC_ASSERT_UNLOCKED(pdp) \
168    PWDDESC_LOCK_ASSERT((pdp), MA_NOTOWNED)
169
170#define	PWDDESC_XLOCKED_LOAD_PWD(pdp)	({					\
171	struct pwddesc *_pdp = (pdp);						\
172	struct pwd *_pwd;							\
173	_pwd = smr_serialized_load(&(_pdp)->pd_pwd,				\
174	    (PWDDESC_ASSERT_XLOCKED(_pdp), true));				\
175	_pwd;									\
176})
177
178/* Lock a file descriptor table. */
179#define	FILEDESC_LOCK_INIT(fdp)	sx_init(&(fdp)->fd_sx, "filedesc structure")
180#define	FILEDESC_LOCK_DESTROY(fdp)	sx_destroy(&(fdp)->fd_sx)
181#define	FILEDESC_LOCK(fdp)	(&(fdp)->fd_sx)
182#define	FILEDESC_XLOCK(fdp)	sx_xlock(&(fdp)->fd_sx)
183#define	FILEDESC_XUNLOCK(fdp)	sx_xunlock(&(fdp)->fd_sx)
184#define	FILEDESC_SLOCK(fdp)	sx_slock(&(fdp)->fd_sx)
185#define	FILEDESC_SUNLOCK(fdp)	sx_sunlock(&(fdp)->fd_sx)
186
187#define	FILEDESC_LOCK_ASSERT(fdp)	sx_assert(&(fdp)->fd_sx, SX_LOCKED | \
188					    SX_NOTRECURSED)
189#define	FILEDESC_XLOCK_ASSERT(fdp)	sx_assert(&(fdp)->fd_sx, SX_XLOCKED | \
190					    SX_NOTRECURSED)
191#define	FILEDESC_UNLOCK_ASSERT(fdp)	sx_assert(&(fdp)->fd_sx, SX_UNLOCKED)
192
193#define	FILEDESC_IS_ONLY_USER(fdp)	({					\
194	struct filedesc *_fdp = (fdp);						\
195	MPASS(curproc->p_fd == _fdp);						\
196	(curproc->p_numthreads == 1 && refcount_load(&_fdp->fd_refcnt) == 1);	\
197})
198
199#else
200
201/*
202 * Accessor for libkvm et al.
203 */
204#define	PWDDESC_KVM_LOAD_PWD(pdp)	({					\
205	struct pwddesc *_pdp = (pdp);						\
206	struct pwd *_pwd;							\
207	_pwd = smr_kvm_load(&(_pdp)->pd_pwd);					\
208	_pwd;									\
209})
210
211#endif
212
213#ifdef _KERNEL
214
215/* Operation types for kern_dup(). */
216enum {
217	FDDUP_NORMAL,		/* dup() behavior. */
218	FDDUP_FCNTL,		/* fcntl()-style errors. */
219	FDDUP_FIXED,		/* Force fixed allocation. */
220	FDDUP_LASTMODE,
221};
222
223/* Flags for kern_dup(). */
224#define	FDDUP_FLAG_CLOEXEC	0x1	/* Atomically set UF_EXCLOSE. */
225
226/* For backward compatibility. */
227#define	falloc(td, resultfp, resultfd, flags) \
228	falloc_caps(td, resultfp, resultfd, flags, NULL)
229
230struct mount;
231struct thread;
232
233static __inline void
234filecaps_init(struct filecaps *fcaps)
235{
236
237        bzero(fcaps, sizeof(*fcaps));
238        fcaps->fc_nioctls = -1;
239}
240bool	filecaps_copy(const struct filecaps *src, struct filecaps *dst,
241	    bool locked);
242void	filecaps_move(struct filecaps *src, struct filecaps *dst);
243void	filecaps_free(struct filecaps *fcaps);
244
245int	closef(struct file *fp, struct thread *td);
246void	closef_nothread(struct file *fp);
247int	descrip_check_write_mp(struct filedesc *fdp, struct mount *mp);
248int	dupfdopen(struct thread *td, struct filedesc *fdp, int dfd, int mode,
249	    int openerror, int *indxp);
250int	falloc_caps(struct thread *td, struct file **resultfp, int *resultfd,
251	    int flags, struct filecaps *fcaps);
252void	falloc_abort(struct thread *td, struct file *fp);
253int	_falloc_noinstall(struct thread *td, struct file **resultfp, u_int n);
254#define	falloc_noinstall(td, resultfp) _falloc_noinstall(td, resultfp, 1)
255void	_finstall(struct filedesc *fdp, struct file *fp, int fd, int flags,
256	    struct filecaps *fcaps);
257int	finstall(struct thread *td, struct file *fp, int *resultfd, int flags,
258	    struct filecaps *fcaps);
259int	finstall_refed(struct thread *td, struct file *fp, int *resultfd, int flags,
260	    struct filecaps *fcaps);
261int	fdalloc(struct thread *td, int minfd, int *result);
262int	fdallocn(struct thread *td, int minfd, int *fds, int n);
263int	fdcheckstd(struct thread *td);
264void	fdclose(struct thread *td, struct file *fp, int idx);
265void	fdcloseexec(struct thread *td);
266void	fdsetugidsafety(struct thread *td);
267struct	filedesc *fdcopy(struct filedesc *fdp);
268void	fdunshare(struct thread *td);
269void	fdescfree(struct thread *td);
270int	fdlastfile(struct filedesc *fdp);
271int	fdlastfile_single(struct filedesc *fdp);
272struct	filedesc *fdinit(void);
273struct	filedesc *fdshare(struct filedesc *fdp);
274struct filedesc_to_leader *
275	filedesc_to_leader_alloc(struct filedesc_to_leader *old,
276	    struct filedesc *fdp, struct proc *leader);
277struct filedesc_to_leader *
278	filedesc_to_leader_share(struct filedesc_to_leader *fdtol,
279	    struct filedesc *fdp);
280int	getvnode(struct thread *td, int fd, cap_rights_t *rightsp,
281	    struct file **fpp);
282int	getvnode_path(struct thread *td, int fd, cap_rights_t *rightsp,
283	    struct file **fpp);
284void	mountcheckdirs(struct vnode *olddp, struct vnode *newdp);
285
286int	fget_cap_noref(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
287	    struct file **fpp, struct filecaps *havecapsp);
288int	fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp,
289	    struct file **fpp, struct filecaps *havecapsp);
290/* Return a referenced file from an unlocked descriptor. */
291int	fget_unlocked(struct thread *td, int fd, cap_rights_t *needrightsp,
292	    struct file **fpp);
293/* Return a file pointer without a ref. FILEDESC_IS_ONLY_USER must be true.  */
294int	fget_only_user(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
295	    struct file **fpp);
296#define	fput_only_user(fdp, fp)	({					\
297	MPASS(FILEDESC_IS_ONLY_USER(fdp));				\
298	MPASS(refcount_load(&fp->f_count) > 0);				\
299})
300
301/* Requires a FILEDESC_{S,X}LOCK held and returns without a ref. */
302static __inline struct file *
303fget_noref(struct filedesc *fdp, int fd)
304{
305
306	FILEDESC_LOCK_ASSERT(fdp);
307
308	if (__predict_false((u_int)fd >= (u_int)fdp->fd_nfiles))
309		return (NULL);
310
311	return (fdp->fd_ofiles[fd].fde_file);
312}
313
314static __inline struct filedescent *
315fdeget_noref(struct filedesc *fdp, int fd)
316{
317	struct filedescent *fde;
318
319	FILEDESC_LOCK_ASSERT(fdp);
320
321	if (__predict_false((u_int)fd >= (u_int)fdp->fd_nfiles))
322		return (NULL);
323
324	fde = &fdp->fd_ofiles[fd];
325	if (__predict_false(fde->fde_file == NULL))
326		return (NULL);
327
328	return (fde);
329}
330
331#ifdef CAPABILITIES
332static __inline bool
333fd_modified(struct filedesc *fdp, int fd, seqc_t seqc)
334{
335
336	return (!seqc_consistent(fd_seqc(fdp->fd_files, fd), seqc));
337}
338#endif
339
340int	proc_nfiles(struct proc *p);
341
342/* cdir/rdir/jdir manipulation functions. */
343struct pwddesc *pdcopy(struct pwddesc *pdp);
344void	pdescfree(struct thread *td);
345struct pwddesc *pdinit(struct pwddesc *pdp, bool keeplock);
346struct pwddesc *pdshare(struct pwddesc *pdp);
347void	pdunshare(struct thread *td);
348
349void	pwd_altroot(struct thread *td, struct vnode *altroot_vp);
350void	pwd_chdir(struct thread *td, struct vnode *vp);
351int	pwd_chroot(struct thread *td, struct vnode *vp);
352int	pwd_chroot_chdir(struct thread *td, struct vnode *vp);
353void	pwd_ensure_dirs(void);
354void	pwd_set_rootvnode(void);
355
356struct pwd *pwd_hold_pwddesc(struct pwddesc *pdp);
357bool	pwd_hold_smr(struct pwd *pwd);
358struct pwd *pwd_hold_proc(struct proc *p);
359struct pwd *pwd_hold(struct thread *td);
360void	pwd_drop(struct pwd *pwd);
361static inline void
362pwd_set(struct pwddesc *pdp, struct pwd *newpwd)
363{
364	smr_serialized_store(&pdp->pd_pwd, newpwd,
365	    (PWDDESC_ASSERT_XLOCKED(pdp), true));
366}
367#define	pwd_get_smr()	vfs_smr_entered_load(&curproc->p_pd->pd_pwd)
368
369#endif /* _KERNEL */
370
371#endif /* !_SYS_FILEDESC_H_ */