42#include "opt_capsicum.h"
44#include "opt_ktrace.h"
49#include <sys/capsicum.h>
53#include <sys/filedesc.h>
56#include <sys/kernel.h>
57#include <sys/limits.h>
59#include <sys/malloc.h>
63#include <sys/selinfo.h>
67#include <sys/protosw.h>
69#include <sys/resourcevar.h>
71#include <sys/signalvar.h>
76#include <sys/syscallsubr.h>
77#include <sys/sysctl.h>
78#include <sys/sysproto.h>
79#include <sys/unistd.h>
82#include <sys/ktrace.h>
86#include <security/audit/audit.h>
93static MALLOC_DEFINE(M_FILEDESC,
"filedesc",
"Open file descriptor table");
97 "file desc to leader structures");
108static int closefp(
struct filedesc *fdp,
int fd,
struct file *fp,
109 struct thread *td,
bool holdleaders,
bool audit);
111 cap_rights_t *rightsp,
struct kinfo_file *kif,
112 struct filedesc *fdp,
int flags);
113static int fd_first_free(
struct filedesc *fdp,
int low,
int size);
114static void fdgrowtable(
struct filedesc *fdp,
int nfd);
116static void fdunused(
struct filedesc *fdp,
int fd);
117static void fdused(
struct filedesc *fdp,
int fd);
119 cap_rights_t *needrightsp,
struct file **fpp, seqc_t *seqp);
120static int getmaxfd(
struct thread *td);
123 struct filecaps *dst, u_long *ioctls);
152#define NDSLOTSIZE sizeof(NDSLOTTYPE)
153#define NDENTRIES (NDSLOTSIZE * __CHAR_BIT)
154#define NDSLOT(x) ((x) / NDENTRIES)
155#define NDBIT(x) ((NDSLOTTYPE)1 << ((x) % NDENTRIES))
156#define NDSLOTS(x) (((x) + NDENTRIES - 1) / NDENTRIES)
158#define FILEDESC_FOREACH_FDE(fdp, _iterator, _fde) \
159 struct filedesc *_fdp = (fdp); \
160 int _lastfile = fdlastfile_single(_fdp); \
161 for (_iterator = 0; _iterator <= _lastfile; _iterator++) \
162 if ((_fde = &_fdp->fd_ofiles[_iterator])->fde_file != NULL)
164#define FILEDESC_FOREACH_FP(fdp, _iterator, _fp) \
165 struct filedesc *_fdp = (fdp); \
166 int _lastfile = fdlastfile_single(_fdp); \
167 for (_iterator = 0; _iterator <= _lastfile; _iterator++) \
168 if ((_fp = _fdp->fd_ofiles[_iterator].fde_file) != NULL)
211 NDSLOTTYPE *map = fdp->fd_map;
221 if ((
mask &= ~map[off]) != 0UL)
225 for (maxoff =
NDSLOTS(size); off < maxoff; ++off)
226 if (map[off] != ~0UL)
227 return (off *
NDENTRIES + ffsl(~map[off]) - 1);
240 NDSLOTTYPE *map = fdp->fd_map;
243 off =
NDSLOT(fdp->fd_nfiles - 1);
244 for (minoff =
NDSLOT(0); off >= minoff; --off)
246 return (off *
NDENTRIES + flsl(map[off]) - 1);
254 FILEDESC_LOCK_ASSERT(fdp);
262 KASSERT(
fd >= 0 && fd < fdp->fd_nfiles,
263 (
"file descriptor %d out of range (0, %d)",
fd, fdp->fd_nfiles));
275 KASSERT(!
fdisused(fdp,
fd), (
"fd=%d is already used",
fd));
284 FILEDESC_XLOCK_ASSERT(fdp);
287 if (
fd == fdp->fd_freefile)
298 FILEDESC_XLOCK_ASSERT(fdp);
300 KASSERT(
fdisused(fdp,
fd), (
"fd=%d is already unused",
fd));
301 KASSERT(fdp->fd_ofiles[
fd].fde_file == NULL,
302 (
"fd=%d is still in use",
fd));
305 if (fd < fdp->fd_freefile)
306 fdp->fd_freefile =
fd;
324 struct filedescent *fde;
326 FILEDESC_XLOCK_ASSERT(fdp);
327 fde = &fdp->fd_ofiles[
fd];
329 seqc_write_begin(&fde->fde_seqc);
331 fde->fde_file = NULL;
333 seqc_write_end(&fde->fde_seqc);
342#ifndef _SYS_SYSPROTO_H_
357 PROC_LOCK(td->td_proc);
358 lim = racct_get_limit(td->td_proc, RACCT_NOFILE);
359 PROC_UNLOCK(td->td_proc);
360 if (lim < td->td_retval[0])
361 td->td_retval[0] = lim;
372#ifndef _SYS_SYSPROTO_H_
383 return (
kern_dup(td, FDDUP_FIXED, 0, (
int)uap->
from, (
int)uap->
to));
389#ifndef _SYS_SYSPROTO_H_
399 return (
kern_dup(td, FDDUP_NORMAL, 0, (
int)uap->
fd, 0));
405#ifndef _SYS_SYSPROTO_H_
437 error = copyin((
void *)(intptr_t)arg, &ofl,
sizeof(ofl));
438 fl.l_start = ofl.l_start;
439 fl.l_len = ofl.l_len;
440 fl.l_pid = ofl.l_pid;
441 fl.l_type = ofl.l_type;
442 fl.l_whence = ofl.l_whence;
456 arg1 = (intptr_t)&fl;
462 error = copyin((
void *)(intptr_t)arg, &fl,
sizeof(fl));
463 arg1 = (intptr_t)&fl;
474 if (cmd == F_OGETLK) {
475 ofl.l_start = fl.l_start;
476 ofl.l_len = fl.l_len;
477 ofl.l_pid = fl.l_pid;
478 ofl.l_type = fl.l_type;
479 ofl.l_whence = fl.l_whence;
480 error = copyout(&ofl, (
void *)(intptr_t)arg,
sizeof(ofl));
481 }
else if (cmd == F_GETLK) {
482 error = copyout(&fl, (
void *)(intptr_t)arg,
sizeof(fl));
490 struct filedesc *fdp;
492 struct file *fp, *fp2;
493 struct filedescent *fde;
497 struct kinfo_file *kif;
498 int error, flg, kif_sz, seals, tmp;
512 error =
kern_dup(td, FDDUP_FCNTL, 0,
fd, tmp);
515 case F_DUPFD_CLOEXEC:
517 error =
kern_dup(td, FDDUP_FCNTL, FDDUP_FLAG_CLOEXEC,
fd, tmp);
522 error =
kern_dup(td, FDDUP_FIXED, 0,
fd, tmp);
525 case F_DUP2FD_CLOEXEC:
527 error =
kern_dup(td, FDDUP_FIXED, FDDUP_FLAG_CLOEXEC,
fd, tmp);
533 fde = fdeget_noref(fdp,
fd);
536 (fde->fde_flags & UF_EXCLOSE) ? FD_CLOEXEC : 0;
539 FILEDESC_SUNLOCK(fdp);
545 fde = fdeget_noref(fdp,
fd);
547 fde->fde_flags = (fde->fde_flags & ~UF_EXCLOSE) |
548 (arg & FD_CLOEXEC ? UF_EXCLOSE : 0);
551 FILEDESC_XUNLOCK(fdp);
558 td->td_retval[0] = OFLAGS(fp->f_flag);
572 tmp = flg = fp->f_flag;
574 tmp |= FFLAGS(arg & ~O_ACCMODE) & FCNTLFLAGS;
575 }
while (atomic_cmpset_int(&fp->f_flag, flg, tmp) == 0);
576 tmp = fp->f_flag & FNONBLOCK;
577 error = fo_ioctl(fp, FIONBIO, &tmp, td->td_ucred, td);
582 tmp = fp->f_flag & FASYNC;
583 error = fo_ioctl(fp, FIOASYNC, &tmp, td->td_ucred, td);
588 atomic_clear_int(&fp->f_flag, FNONBLOCK);
590 (void)fo_ioctl(fp, FIONBIO, &tmp, td->td_ucred, td);
598 error = fo_ioctl(fp, FIOGETOWN, &tmp, td->td_ucred, td);
600 td->td_retval[0] = tmp;
609 error = fo_ioctl(fp, FIOSETOWN, &tmp, td->td_ucred, td);
626 flp = (
struct flock *)arg;
627 if ((flg & F_REMOTE) != 0 && flp->l_sysid == 0) {
635 if (fp->f_type != DTYPE_VNODE || fp->f_ops == &
path_fileops) {
641 if (flp->l_whence == SEEK_CUR) {
642 foffset = foffset_get(fp);
645 foffset > OFF_MAX - flp->l_start)) {
650 flp->l_start += foffset;
654 switch (flp->l_type) {
656 if ((fp->f_flag & FREAD) == 0) {
660 if ((p->p_leader->p_flag & P_ADVLOCK) == 0) {
661 PROC_LOCK(p->p_leader);
662 p->p_leader->p_flag |= P_ADVLOCK;
663 PROC_UNLOCK(p->p_leader);
665 error = VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_SETLK,
669 if ((fp->f_flag & FWRITE) == 0) {
673 if ((p->p_leader->p_flag & P_ADVLOCK) == 0) {
674 PROC_LOCK(p->p_leader);
675 p->p_leader->p_flag |= P_ADVLOCK;
676 PROC_UNLOCK(p->p_leader);
678 error = VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_SETLK,
682 error = VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_UNLCK,
686 if (flg != F_REMOTE) {
690 error = VOP_ADVLOCK(vp, (caddr_t)p->p_leader,
691 F_UNLCKSYS, flp, flg);
697 if (error != 0 || flp->l_type == F_UNLCK ||
698 flp->l_type == F_UNLCKSYS) {
725 flp->l_whence = SEEK_SET;
728 flp->l_type = F_UNLCK;
729 (void) VOP_ADVLOCK(vp, (caddr_t)p->p_leader,
730 F_UNLCK, flp, F_POSIX);
740 if (fp->f_type != DTYPE_VNODE || fp->f_ops == &
path_fileops) {
745 flp = (
struct flock *)arg;
746 if (flp->l_type != F_RDLCK && flp->l_type != F_WRLCK &&
747 flp->l_type != F_UNLCK) {
752 if (flp->l_whence == SEEK_CUR) {
753 foffset = foffset_get(fp);
754 if ((flp->l_start > 0 &&
755 foffset > OFF_MAX - flp->l_start) ||
757 foffset < OFF_MIN - flp->l_start)) {
762 flp->l_start += foffset;
765 error = VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_GETLK, flp,
774 error = fo_add_seals(fp, arg);
782 if (fo_get_seals(fp, &seals) == 0)
783 td->td_retval[0] = seals;
790 arg = arg ? 128 * 1024: 0;
796 if (fp->f_type != DTYPE_VNODE || fp->f_ops == &
path_fileops) {
802 if (vp->v_type != VREG) {
812 error = vn_lock(vp, LK_EXCLUSIVE);
818 bsize = fp->f_vnode->v_mount->mnt_stat.f_iosize;
819 arg = MIN(arg, INT_MAX - bsize + 1);
820 fp->f_seqcount[UIO_READ] = MIN(IO_SEQMAX,
821 (arg + bsize - 1) / bsize);
822 atomic_set_int(&fp->f_flag, FRDAHEAD);
824 atomic_clear_int(&fp->f_flag, FRDAHEAD);
847 if (fp->f_type != DTYPE_VNODE) {
860 mp = atomic_load_ptr(&vp->v_mount);
861 if (__predict_false(mp == NULL)) {
866 td->td_retval[0] = 0;
867 if (mp->mnt_kern_flag & MNTK_UNIONFS ||
868 mp->mnt_flag & MNT_UNION)
869 td->td_retval[0] = 1;
874#ifdef CAPABILITY_MODE
875 if (IN_CAPABILITY_MODE(td)) {
880 error = copyin((
void *)arg, &kif_sz,
sizeof(kif_sz));
883 if (kif_sz !=
sizeof(*kif)) {
887 kif =
malloc(
sizeof(*kif), M_TEMP, M_WAITOK | M_ZERO);
890 if (error == 0 && fhold(fp)) {
892 FILEDESC_SUNLOCK(fdp);
894 if ((kif->kf_status & KF_ATTR_VALID) != 0) {
895 kif->kf_structsize =
sizeof(*kif);
896 error = copyout(kif, (
void *)arg,
sizeof(*kif));
901 FILEDESC_SUNLOCK(fdp);
928 struct filedesc *fdp;
929 struct filedescent *oldfde, *newfde;
931 struct file *delfp, *oldfp;
932 u_long *oioctls, *nioctls;
939 MPASS((
flags & ~(FDDUP_FLAG_CLOEXEC)) == 0);
940 MPASS(
mode < FDDUP_LASTMODE);
953 return (
mode == FDDUP_FCNTL ? EINVAL : EBADF);
956 return (
mode == FDDUP_FCNTL ? EINVAL : EBADF);
960 if (fget_noref(fdp, old) == NULL)
962 if (
mode == FDDUP_FIXED && old ==
new) {
963 td->td_retval[0] =
new;
964 if (
flags & FDDUP_FLAG_CLOEXEC)
965 fdp->fd_ofiles[
new].fde_flags |= UF_EXCLOSE;
970 oldfde = &fdp->fd_ofiles[old];
971 oldfp = oldfde->fde_file;
983 if ((error =
fdalloc(td,
new, &
new)) != 0) {
989 if (
new >= fdp->fd_nfiles) {
999 if (RACCT_ENABLED()) {
1000 error = racct_set_unlocked(p, RACCT_NOFILE,
new + 1);
1014 KASSERT(0, (
"%s unsupported mode %d", __func__,
mode));
1017 KASSERT(old !=
new, (
"new fd is same as old"));
1020 oldfde = &fdp->fd_ofiles[old];
1021 KASSERT(oldfp == oldfde->fde_file,
1022 (
"fdt_ofiles shift from growth observed at fd %d",
1025 newfde = &fdp->fd_ofiles[
new];
1026 delfp = newfde->fde_file;
1034 seqc_write_begin(&newfde->fde_seqc);
1037 fde_copy(oldfde, newfde);
1040 if ((
flags & FDDUP_FLAG_CLOEXEC) != 0)
1041 newfde->fde_flags = oldfde->fde_flags | UF_EXCLOSE;
1043 newfde->fde_flags = oldfde->fde_flags & ~UF_EXCLOSE;
1045 seqc_write_end(&newfde->fde_seqc);
1047 td->td_retval[0] =
new;
1051 if (delfp != NULL) {
1052 (void)
closefp(fdp,
new, delfp, td,
true,
false);
1053 FILEDESC_UNLOCK_ASSERT(fdp);
1056 FILEDESC_XUNLOCK(fdp);
1066 crfree(sigio->sio_ucred);
1067 free(sigio, M_SIGIO);
1070static struct sigio *
1076 SIGIO_ASSERT_LOCKED();
1080 *sigio->sio_myref = NULL;
1081 if (sigio->sio_pgid < 0) {
1082 pg = sigio->sio_pgrp;
1084 SLIST_REMOVE(&pg->pg_sigiolst, sigio, sigio, sio_pgsigio);
1087 p = sigio->sio_proc;
1089 SLIST_REMOVE(&p->p_sigiolst, sigio, sigio, sio_pgsigio);
1103 struct sigio *sigio;
1106 if (*sigiop == NULL)
1127 struct sigio *sigio, *tmp;
1130 sigio = SLIST_FIRST(sigiolst);
1138 sigio = SLIST_FIRST(sigiolst);
1139 if (sigio == NULL) {
1147 if (sigio->sio_pgid < 0) {
1148 pg = sigio->sio_pgrp;
1152 p = sigio->sio_proc;
1154 KASSERT((p->p_flag & P_WEXIT) != 0,
1155 (
"%s: process %p is not exiting", __func__, p));
1158 SLIST_FOREACH(sigio, sigiolst, sio_pgsigio) {
1159 *sigio->sio_myref = NULL;
1161 KASSERT(sigio->sio_pgid < 0,
1162 (
"Proc sigio in pgrp sigio list"));
1163 KASSERT(sigio->sio_pgrp == pg,
1164 (
"Bogus pgrp in sigio list"));
1166 KASSERT(sigio->sio_pgid > 0,
1167 (
"Pgrp sigio in proc sigio list"));
1168 KASSERT(sigio->sio_proc == p,
1169 (
"Bogus proc in sigio list"));
1179 SLIST_FOREACH_SAFE(sigio, sigiolst, sio_pgsigio, tmp)
1194 struct sigio *osigio, *sigio;
1202 sigio =
malloc(
sizeof(
struct sigio), M_SIGIO, M_WAITOK);
1203 sigio->sio_pgid = pgid;
1204 sigio->sio_ucred =
crhold(curthread->td_ucred);
1205 sigio->sio_myref = sigiop;
1209 ret =
pget(pgid, PGET_NOTWEXIT | PGET_NOTID | PGET_HOLD, &proc);
1215 if ((proc->p_flag & P_WEXIT) != 0) {
1217 }
else if (proc->p_session !=
1218 curthread->td_proc->p_session) {
1229 sigio->sio_proc = proc;
1230 SLIST_INSERT_HEAD(&proc->p_sigiolst, sigio,
1243 if (pgrp->pg_session != curthread->td_proc->p_session) {
1254 sigio->sio_pgrp = pgrp;
1255 SLIST_INSERT_HEAD(&pgrp->pg_sigiolst, sigio,
1279 pgid = (*sigiop != NULL) ? (*sigiop)->sio_pgid : 0;
1290 FILEDESC_XLOCK_ASSERT(fdp);
1298 if (__predict_false(!TAILQ_EMPTY(&fdp->fd_kqlist)))
1304 if (__predict_false(fp->f_type == DTYPE_MQUEUE))
1306 FILEDESC_XUNLOCK(fdp);
1309 if (AUDITING_TD(td) && audit)
1310 audit_sysclose(td,
fd, fp);
1319 if (error == ERESTART)
1326closefp_hl(
struct filedesc *fdp,
int fd,
struct file *fp,
struct thread *td,
1327 bool holdleaders,
bool audit)
1331 FILEDESC_XLOCK_ASSERT(fdp);
1334 if (td->td_proc->p_fdtol != NULL) {
1339 fdp->fd_holdleaderscount++;
1341 holdleaders =
false;
1347 FILEDESC_XLOCK(fdp);
1348 fdp->fd_holdleaderscount--;
1349 if (fdp->fd_holdleaderscount == 0 &&
1350 fdp->fd_holdleaderswakeup != 0) {
1351 fdp->fd_holdleaderswakeup = 0;
1352 wakeup(&fdp->fd_holdleaderscount);
1354 FILEDESC_XUNLOCK(fdp);
1360closefp(
struct filedesc *fdp,
int fd,
struct file *fp,
struct thread *td,
1361 bool holdleaders,
bool audit)
1364 FILEDESC_XLOCK_ASSERT(fdp);
1366 if (__predict_false(td->td_proc->p_fdtol != NULL)) {
1367 return (
closefp_hl(fdp,
fd, fp, td, holdleaders, audit));
1376#ifndef _SYS_SYSPROTO_H_
1392 struct filedesc *fdp;
1395 fdp = td->td_proc->p_fd;
1397 FILEDESC_XLOCK(fdp);
1398 if ((fp = fget_noref(fdp,
fd)) == NULL) {
1399 FILEDESC_XUNLOCK(fdp);
1405 return (
closefp(fdp,
fd, fp, td,
true,
true));
1411 struct filedesc *fdp;
1412 struct fdescenttbl *fdt;
1413 struct filedescent *fde;
1416 fdp = td->td_proc->p_fd;
1417 FILEDESC_XLOCK(fdp);
1418 fdt = atomic_load_ptr(&fdp->fd_files);
1419 highfd = MIN(highfd, fdt->fdt_nfiles - 1);
1421 if (__predict_false(
fd > highfd)) {
1424 for (;
fd <= highfd;
fd++) {
1425 fde = &fdt->fdt_ofiles[
fd];
1426 if (fde->fde_file != NULL)
1427 fde->fde_flags |= UF_EXCLOSE;
1430 FILEDESC_XUNLOCK(fdp);
1437 struct filedesc *fdp;
1438 const struct fdescenttbl *fdt;
1442 fdp = td->td_proc->p_fd;
1443 FILEDESC_XLOCK(fdp);
1444 fdt = atomic_load_ptr(&fdp->fd_files);
1445 highfd = MIN(highfd, fdt->fdt_nfiles - 1);
1447 if (__predict_false(
fd > highfd)) {
1451 fp = fdt->fdt_ofiles[
fd].fde_file;
1457 (void)
closefp(fdp,
fd, fp, td,
true,
true);
1460 FILEDESC_XLOCK(fdp);
1461 fdt = atomic_load_ptr(&fdp->fd_files);
1466 FILEDESC_XUNLOCK(fdp);
1481 if (highfd < lowfd) {
1485 if ((
flags & CLOSE_RANGE_CLOEXEC) != 0)
1491#ifndef _SYS_SYSPROTO_H_
1502 AUDIT_ARG_FD(uap->
lowfd);
1503 AUDIT_ARG_CMD(uap->
highfd);
1504 AUDIT_ARG_FFLAGS(uap->
flags);
1506 if ((uap->
flags & ~(CLOSE_RANGE_CLOEXEC)) != 0)
1511#ifdef COMPAT_FREEBSD12
1515#ifndef _SYS_SYSPROTO_H_
1516struct freebsd12_closefrom_args {
1522freebsd12_closefrom(
struct thread *td,
struct freebsd12_closefrom_args *uap)
1526 AUDIT_ARG_FD(uap->lowfd);
1532 lowfd = MAX(0, uap->lowfd);
1537#if defined(COMPAT_43)
1541#ifndef _SYS_SYSPROTO_H_
1549ofstat(
struct thread *td,
struct ofstat_args *uap)
1558 error = copyout(&oub, uap->sb,
sizeof(oub));
1564#if defined(COMPAT_FREEBSD11)
1566freebsd11_fstat(
struct thread *td,
struct freebsd11_fstat_args *uap)
1569 struct freebsd11_stat osb;
1575 error = freebsd11_cvtstat(&sb, &osb);
1577 error = copyout(&osb, uap->sb,
sizeof(osb));
1585#ifndef _SYS_SYSPROTO_H_
1600 error = copyout(&ub, uap->
sb,
sizeof(ub));
1613 if (__predict_false(error != 0))
1616 AUDIT_ARG_FILE(td->td_proc, fp);
1618 error = fo_stat(fp, sbp, td->td_ucred);
1620#ifdef __STAT_TIME_T_EXT
1621 sbp->st_atim_ext = 0;
1622 sbp->st_mtim_ext = 0;
1623 sbp->st_ctim_ext = 0;
1624 sbp->st_btim_ext = 0;
1627 if (KTRPOINT(td, KTR_STRUCT))
1628 ktrstat_error(sbp, error);
1633#if defined(COMPAT_FREEBSD11)
1637#ifndef _SYS_SYSPROTO_H_
1638struct freebsd11_nfstat_args {
1645freebsd11_nfstat(
struct thread *td,
struct freebsd11_nfstat_args *uap)
1654 error = freebsd11_cvtnstat(&ub, &nub);
1656 error = copyout(&nub, uap->sb,
sizeof(nub));
1664#ifndef _SYS_SYSPROTO_H_
1679 td->td_retval[0] =
value;
1694 if (
name == _PC_ASYNC_IO) {
1695 *valuep = _POSIX_ASYNCHRONOUS_IO;
1700 vn_lock(vp, LK_SHARED | LK_RETRY);
1701 error = VOP_PATHCONF(vp,
name, valuep);
1703 }
else if (fp->f_type == DTYPE_PIPE || fp->f_type == DTYPE_SOCKET) {
1704 if (
name != _PC_PIPE_BUF) {
1732 if (
src->fc_ioctls != NULL && !locked)
1734 memcpy(dst,
src,
sizeof(*
src));
1735 if (
src->fc_ioctls == NULL)
1738 KASSERT(
src->fc_nioctls > 0,
1739 (
"fc_ioctls != NULL, but fc_nioctls=%hd",
src->fc_nioctls));
1741 size =
sizeof(
src->fc_ioctls[0]) *
src->fc_nioctls;
1742 dst->fc_ioctls =
malloc(size, M_FILECAPS, M_WAITOK);
1743 memcpy(dst->fc_ioctls,
src->fc_ioctls, size);
1753 if (__predict_true(
src->fc_ioctls == NULL))
1756 KASSERT(
src->fc_nioctls > 0,
1757 (
"fc_ioctls != NULL, but fc_nioctls=%hd",
src->fc_nioctls));
1759 size =
sizeof(
src->fc_ioctls[0]) *
src->fc_nioctls;
1760 ioctls =
malloc(size, M_FILECAPS, M_WAITOK);
1771 if (__predict_true(
src->fc_ioctls == NULL)) {
1772 MPASS(ioctls == NULL);
1776 size =
sizeof(
src->fc_ioctls[0]) *
src->fc_nioctls;
1777 dst->fc_ioctls = ioctls;
1778 bcopy(
src->fc_ioctls, dst->fc_ioctls, size);
1789 bzero(
src,
sizeof(*
src));
1799 CAP_ALL(&fcaps->fc_rights);
1800 fcaps->fc_ioctls = NULL;
1801 fcaps->fc_nioctls = -1;
1802 fcaps->fc_fcntls = CAP_FCNTL_ALL;
1812 free(fcaps->fc_ioctls, M_FILECAPS);
1813 bzero(fcaps,
sizeof(*fcaps));
1821 ioctls = fcaps->fc_ioctls;
1822 bzero(fcaps,
sizeof(*fcaps));
1830 free(ioctls, M_FILECAPS);
1841 (
"%s: invalid rights", func));
1842 KASSERT((fcaps->fc_fcntls & ~CAP_FCNTL_ALL) == 0,
1843 (
"%s: invalid fcntls", func));
1844 KASSERT(fcaps->fc_fcntls == 0 ||
1845 cap_rights_is_set(&fcaps->fc_rights, CAP_FCNTL),
1846 (
"%s: fcntls without CAP_FCNTL", func));
1847 KASSERT(fcaps->fc_ioctls != NULL ? fcaps->fc_nioctls > 0 :
1848 (fcaps->fc_nioctls == -1 || fcaps->fc_nioctls == 0),
1849 (
"%s: invalid ioctls", func));
1850 KASSERT(fcaps->fc_nioctls == 0 ||
1851 cap_rights_is_set(&fcaps->fc_rights, CAP_IOCTL),
1852 (
"%s: ioctls without CAP_IOCTL", func));
1860 FILEDESC_XLOCK_ASSERT(fdp);
1862 nfd1 = fdp->fd_nfiles * 2;
1876 struct fdescenttbl *ntable;
1877 struct fdescenttbl *otable;
1878 int nnfiles, onfiles;
1879 NDSLOTTYPE *nmap, *omap;
1881 KASSERT(fdp->fd_nfiles > 0, (
"zero-length file table"));
1884 onfiles = fdp->fd_nfiles;
1885 otable = fdp->fd_files;
1890 if (nnfiles <= onfiles)
1901 ntable =
malloc(offsetof(
struct fdescenttbl, fdt_ofiles) +
1902 nnfiles *
sizeof(ntable->fdt_ofiles[0]) +
1904 M_FILEDESC, M_ZERO | M_WAITOK);
1906 ntable->fdt_nfiles = nnfiles;
1907 memcpy(ntable->fdt_ofiles, otable->fdt_ofiles,
1908 onfiles *
sizeof(ntable->fdt_ofiles[0]));
1919 memcpy(nmap, omap,
NDSLOTS(onfiles) *
sizeof(*omap));
1928 atomic_store_rel_ptr((
volatile void *)&fdp->fd_files, (uintptr_t)ntable);
1949 if (curproc->p_fd != fdp || FILEDESC_IS_ONLY_USER(fdp)) {
1950 free(otable, M_FILEDESC);
1952 ft = (
struct freetable *)&otable->fdt_ofiles[onfiles];
1955 SLIST_INSERT_HEAD(&fdp0->fd_free, ft, ft_next);
1964 free(omap, M_FILEDESC);
1973 struct proc *p = td->td_proc;
1974 struct filedesc *fdp = p->p_fd;
1975 int fd, maxfd, allocfd;
1980 FILEDESC_XLOCK_ASSERT(fdp);
1982 if (fdp->fd_freefile > minfd)
1983 minfd = fdp->fd_freefile;
1992 if (__predict_false(
fd >= maxfd))
1994 if (__predict_false(
fd >= fdp->fd_nfiles)) {
1995 allocfd = min(
fd * 2, maxfd);
1997 if (RACCT_ENABLED()) {
1998 error = racct_set_unlocked(p, RACCT_NOFILE, allocfd);
2014 KASSERT(
fd >= 0 &&
fd < min(maxfd, fdp->fd_nfiles),
2015 (
"invalid descriptor %d",
fd));
2017 (
"fd_first_free() returned non-free descriptor"));
2018 KASSERT(fdp->fd_ofiles[
fd].fde_file == NULL,
2019 (
"file descriptor isn't free"));
2031 struct proc *p = td->td_proc;
2032 struct filedesc *fdp = p->p_fd;
2035 FILEDESC_XLOCK_ASSERT(fdp);
2037 for (i = 0; i < n; i++)
2038 if (
fdalloc(td, 0, &fds[i]) != 0)
2042 for (i--; i >= 0; i--)
2059 struct filecaps *fcaps)
2064 MPASS(resultfp != NULL);
2065 MPASS(resultfd != NULL);
2068 if (__predict_false(error != 0)) {
2073 if (__predict_false(error != 0)) {
2093 static struct timeval lastfail;
2096 KASSERT(resultfp != NULL, (
"%s: resultfp == NULL", __func__));
2099 openfiles_new = atomic_fetchadd_int(&
openfiles, 1) + 1;
2100 if ((openfiles_new >= maxuserfiles &&
2105 printf(
"kern.maxfiles limit exceeded by uid %i, (%s) "
2106 "please see tuning(7).\n", td->td_ucred->cr_ruid, td->td_proc->p_comm);
2111 bzero(fp,
sizeof(*fp));
2112 refcount_init(&fp->f_count, n);
2113 fp->f_cred =
crhold(td->td_ucred);
2126 refcount_init(&fp->f_count, 0);
2135 struct filecaps *fcaps)
2137 struct filedescent *fde;
2142 FILEDESC_XLOCK_ASSERT(fdp);
2144 fde = &fdp->fd_ofiles[
fd];
2146 seqc_write_begin(&fde->fde_seqc);
2149 fde->fde_flags = (
flags & O_CLOEXEC) != 0 ? UF_EXCLOSE : 0;
2155 seqc_write_end(&fde->fde_seqc);
2161 struct filecaps *fcaps)
2163 struct filedesc *fdp = td->td_proc->p_fd;
2168 FILEDESC_XLOCK(fdp);
2170 if (__predict_true(error == 0)) {
2173 FILEDESC_XUNLOCK(fdp);
2179 struct filecaps *fcaps)
2188 if (__predict_false(error != 0)) {
2203 struct filedesc *newfdp;
2206 newfdp = &newfdp0->
fd_fd;
2209 FILEDESC_LOCK_INIT(newfdp);
2210 refcount_init(&newfdp->fd_refcnt, 1);
2211 refcount_init(&newfdp->fd_holdcnt, 1);
2212 newfdp->fd_map = newfdp0->fd_dmap;
2213 newfdp->fd_files = (
struct fdescenttbl *)&newfdp0->fd_dfiles;
2214 newfdp->fd_files->fdt_nfiles =
NDFILE;
2228 struct pwddesc *newpdp;
2231 newpdp =
malloc(
sizeof(*newpdp), M_PWDDESC, M_WAITOK | M_ZERO);
2233 PWDDESC_LOCK_INIT(newpdp);
2234 refcount_init(&newpdp->pd_refcount, 1);
2235 newpdp->pd_cmask = CMASK;
2239 smr_serialized_store(&newpdp->pd_pwd, newpwd,
true);
2245 smr_serialized_store(&newpdp->pd_pwd, newpwd,
true);
2247 PWDDESC_XUNLOCK(pdp);
2266static struct filedesc *
2269 struct filedesc *fdp;
2271 PROC_LOCK_ASSERT(p, MA_OWNED);
2272 fdp = atomic_load_ptr(&p->p_fd);
2274 refcount_acquire(&fdp->fd_holdcnt);
2278static struct pwddesc *
2281 struct pwddesc *pdp;
2283 PROC_LOCK_ASSERT(p, MA_OWNED);
2284 pdp = atomic_load_ptr(&p->p_pd);
2286 refcount_acquire(&pdp->pd_refcount);
2294 if (refcount_load(&fdp->fd_holdcnt) > 1) {
2295 if (refcount_release(&fdp->fd_holdcnt) == 0)
2299 FILEDESC_LOCK_DESTROY(fdp);
2308 if (refcount_release_if_not_last(&pdp->pd_refcount))
2312 if (refcount_release(&pdp->pd_refcount) == 0) {
2313 PWDDESC_XUNLOCK(pdp);
2316 pwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
2318 PWDDESC_XUNLOCK(pdp);
2321 PWDDESC_LOCK_DESTROY(pdp);
2322 free(pdp, M_PWDDESC);
2332 refcount_acquire(&fdp->fd_refcnt);
2342 refcount_acquire(&pdp->pd_refcount);
2352 struct filedesc *tmp;
2353 struct proc *p = td->td_proc;
2355 if (refcount_load(&p->p_fd->fd_refcnt) == 1)
2369 struct pwddesc *pdp;
2374 if (refcount_load(&p->p_pd->pd_refcount) == 1)
2389 struct filedesc *newfdp;
2390 struct filedescent *nfde, *ofde;
2396 FILEDESC_SLOCK(fdp);
2399 if (lastfile < newfdp->fd_nfiles)
2401 FILEDESC_SUNLOCK(fdp);
2403 FILEDESC_SLOCK(fdp);
2406 newfdp->fd_freefile = fdp->fd_freefile;
2408 if ((ofde->fde_file->f_ops->fo_flags & DFLAG_PASSABLE) == 0 ||
2409 !fhold(ofde->fde_file)) {
2410 if (newfdp->fd_freefile == fdp->fd_freefile)
2411 newfdp->fd_freefile = i;
2414 nfde = &newfdp->fd_ofiles[i];
2419 MPASS(newfdp->fd_freefile != -1);
2420 FILEDESC_SUNLOCK(fdp);
2430 struct pwddesc *newpdp;
2434 newpdp =
pdinit(pdp,
true);
2435 newpdp->pd_cmask = pdp->pd_cmask;
2436 PWDDESC_XUNLOCK(pdp);
2447 struct filedesc *fdp;
2448 struct filedesc_to_leader *fdtol;
2458 MPASS(fdtol != NULL);
2460 FILEDESC_XLOCK(fdp);
2461 KASSERT(fdtol->fdl_refcount > 0,
2462 (
"filedesc_to_refcount botch: fdl_refcount=%d",
2463 fdtol->fdl_refcount));
2464 if (fdtol->fdl_refcount == 1 &&
2465 (p->p_leader->p_flag & P_ADVLOCK) != 0) {
2467 if (fp->f_type != DTYPE_VNODE ||
2470 FILEDESC_XUNLOCK(fdp);
2471 lf.l_whence = SEEK_SET;
2474 lf.l_type = F_UNLCK;
2476 (void) VOP_ADVLOCK(vp,
2477 (caddr_t)p->p_leader, F_UNLCK,
2479 FILEDESC_XLOCK(fdp);
2484 if (fdtol->fdl_refcount == 1) {
2485 if (fdp->fd_holdleaderscount > 0 &&
2486 (p->p_leader->p_flag & P_ADVLOCK) != 0) {
2491 fdp->fd_holdleaderswakeup = 1;
2492 sx_sleep(&fdp->fd_holdleaderscount,
2493 FILEDESC_LOCK(fdp), PLOCK,
"fdlhold", 0);
2496 if (fdtol->fdl_holdcount > 0) {
2501 fdtol->fdl_wakeup = 1;
2502 sx_sleep(fdtol, FILEDESC_LOCK(fdp), PLOCK,
2507 fdtol->fdl_refcount--;
2508 if (fdtol->fdl_refcount == 0 &&
2509 fdtol->fdl_holdcount == 0) {
2510 fdtol->fdl_next->fdl_prev = fdtol->fdl_prev;
2511 fdtol->fdl_prev->fdl_next = fdtol->fdl_next;
2515 FILEDESC_XUNLOCK(fdp);
2517 free(fdtol, M_FILEDESC_TO_LEADER);
2528 struct filedescent *fde;
2532 KASSERT(refcount_load(&fdp->fd_refcnt) == 0,
2533 (
"%s: fd table %p carries references", __func__, fdp));
2538 if (refcount_load(&fdp->fd_holdcnt) > 1) {
2539 FILEDESC_XLOCK(fdp);
2540 FILEDESC_XUNLOCK(fdp);
2550 free(fdp->fd_map, M_FILEDESC);
2551 if (fdp->fd_nfiles >
NDFILE)
2552 free(fdp->fd_files, M_FILEDESC);
2555 SLIST_FOREACH_SAFE(ft, &fdp0->fd_free, ft_next, tft)
2565 struct filedesc *fdp;
2572 if (RACCT_ENABLED())
2573 racct_set_unlocked(p, RACCT_NOFILE, 0);
2576 if (p->p_fdtol != NULL)
2582 atomic_store_ptr(&p->p_fd, NULL);
2583 atomic_thread_fence_seq_cst();
2584 PROC_WAIT_UNLOCKED(p);
2586 if (refcount_release(&fdp->fd_refcnt) == 0)
2596 struct pwddesc *pdp;
2605 atomic_store_ptr(&p->p_pd, NULL);
2606 atomic_thread_fence_seq_cst();
2607 PROC_WAIT_UNLOCKED(p);
2626 if (fp->f_type != DTYPE_VNODE)
2630 return ((vp->v_vflag & VV_PROCDEP) != 0);
2639 struct filedesc *fdp;
2643 fdp = td->td_proc->p_fd;
2644 KASSERT(refcount_load(&fdp->fd_refcnt) == 1,
2645 (
"the fdtable should not be shared"));
2646 MPASS(fdp->fd_nfiles >= 3);
2647 for (i = 0; i <= 2; i++) {
2648 fp = fdp->fd_ofiles[i].fde_file;
2650 FILEDESC_XLOCK(fdp);
2657 FILEDESC_XUNLOCK(fdp);
2671fdclose(
struct thread *td,
struct file *fp,
int idx)
2673 struct filedesc *fdp = td->td_proc->p_fd;
2675 FILEDESC_XLOCK(fdp);
2676 if (fdp->fd_ofiles[idx].fde_file == fp) {
2678 FILEDESC_XUNLOCK(fdp);
2681 FILEDESC_XUNLOCK(fdp);
2690 struct filedesc *fdp;
2691 struct filedescent *fde;
2695 fdp = td->td_proc->p_fd;
2696 KASSERT(refcount_load(&fdp->fd_refcnt) == 1,
2697 (
"the fdtable should not be shared"));
2700 if (fp->f_type == DTYPE_MQUEUE ||
2701 (fde->fde_flags & UF_EXCLOSE)) {
2702 FILEDESC_XLOCK(fdp);
2704 (void)
closefp(fdp, i, fp, td,
false,
false);
2705 FILEDESC_UNLOCK_ASSERT(fdp);
2720 struct filedesc *fdp;
2722 int i, error, devnull;
2724 fdp = td->td_proc->p_fd;
2725 KASSERT(refcount_load(&fdp->fd_refcnt) == 1,
2726 (
"the fdtable should not be shared"));
2727 MPASS(fdp->fd_nfiles >= 3);
2729 for (i = 0; i <= 2; i++) {
2730 if (fdp->fd_ofiles[i].fde_file != NULL)
2733 save = td->td_retval[0];
2734 if (devnull != -1) {
2735 error =
kern_dup(td, FDDUP_FIXED, 0, devnull, i);
2738 UIO_SYSSPACE, O_RDWR, 0);
2740 devnull = td->td_retval[0];
2741 KASSERT(devnull == i, (
"we didn't get our fd"));
2744 td->td_retval[0] = save;
2761 struct filedesc_to_leader *fdtol;
2762 struct filedesc *fdp;
2778 if (fp->f_type == DTYPE_VNODE) {
2780 if ((td->td_proc->p_leader->p_flag & P_ADVLOCK) != 0) {
2781 lf.l_whence = SEEK_SET;
2784 lf.l_type = F_UNLCK;
2785 (void) VOP_ADVLOCK(vp, (caddr_t)td->td_proc->p_leader,
2786 F_UNLCK, &lf, F_POSIX);
2788 fdtol = td->td_proc->p_fdtol;
2789 if (fdtol != NULL) {
2794 fdp = td->td_proc->p_fd;
2795 FILEDESC_XLOCK(fdp);
2796 for (fdtol = fdtol->fdl_next;
2797 fdtol != td->td_proc->p_fdtol;
2798 fdtol = fdtol->fdl_next) {
2799 if ((fdtol->fdl_leader->p_flag &
2802 fdtol->fdl_holdcount++;
2803 FILEDESC_XUNLOCK(fdp);
2804 lf.l_whence = SEEK_SET;
2807 lf.l_type = F_UNLCK;
2809 (void) VOP_ADVLOCK(vp,
2810 (caddr_t)fdtol->fdl_leader, F_UNLCK, &lf,
2812 FILEDESC_XLOCK(fdp);
2813 fdtol->fdl_holdcount--;
2814 if (fdtol->fdl_holdcount == 0 &&
2815 fdtol->fdl_wakeup != 0) {
2816 fdtol->fdl_wakeup = 0;
2820 FILEDESC_XUNLOCK(fdp);
2823 return (fdrop_close(fp, td));
2849 atomic_store_rel_ptr((
volatile uintptr_t *)&fp->f_ops, (uintptr_t)ops);
2855 fp->f_seqcount[UIO_READ] = 1;
2856 fp->f_seqcount[UIO_WRITE] = 1;
2857 finit(fp, (
flag & FMASK) | (fp->f_flag & FHASLOCK), DTYPE_VNODE,
2863 struct file **fpp,
struct filecaps *havecapsp)
2865 struct filedescent *fde;
2868 FILEDESC_LOCK_ASSERT(fdp);
2871 fde = fdeget_noref(fdp,
fd);
2878 error = cap_check(cap_rights_fde_inline(fde), needrightsp);
2883 if (havecapsp != NULL)
2886 *fpp = fde->fde_file;
2895fget_cap(
struct thread *td,
int fd, cap_rights_t *needrightsp,
2896 struct file **fpp,
struct filecaps *havecapsp)
2898 struct filedesc *fdp = td->td_proc->p_fd;
2909 if (havecapsp != NULL) {
2911 havecapsp,
false)) {
2917 if (!fd_modified(fdp,
fd, seq))
2926 FILEDESC_SLOCK(fdp);
2928 if (error == 0 && !fhold(*fpp))
2930 FILEDESC_SUNLOCK(fdp);
2936 struct file **fpp,
struct filecaps *havecapsp)
2940 if (havecapsp != NULL && error == 0)
2951 const struct filedescent *fde;
2952 const struct fdescenttbl *fdt;
2953 struct filedesc *fdp;
2956 const cap_rights_t *haverights;
2957 cap_rights_t rights;
2960 VFS_SMR_ASSERT_ENTERED();
2962 rights = *ndp->ni_rightsneeded;
2963 cap_rights_set_one(&rights, CAP_LOOKUP);
2965 fdp = curproc->p_fd;
2966 fdt = fdp->fd_files;
2967 if (__predict_false((u_int)
fd >= fdt->fdt_nfiles))
2969 seq = seqc_read_notmodify(fd_seqc(fdt,
fd));
2970 fde = &fdt->fdt_ofiles[
fd];
2971 haverights = cap_rights_fde_inline(fde);
2973 if (__predict_false(fp == NULL))
2975 if (__predict_false(cap_check_inline_transient(haverights, &rights)))
2977 *fsearch = ((fp->f_flag & FSEARCH) != 0);
2979 if (__predict_false(vp == NULL)) {
2982 if (!
filecaps_copy(&fde->fde_caps, &ndp->ni_filecaps,
false)) {
2989 atomic_thread_fence_acq();
2990 fdt = fdp->fd_files;
2991 if (__predict_false(!seqc_consistent_no_fence(fd_seqc(fdt,
fd), seq)))
3001 if (!cap_rights_contains(&ndp->ni_filecaps.fc_rights, &rights) ||
3002 ndp->ni_filecaps.fc_fcntls != CAP_FCNTL_ALL ||
3003 ndp->ni_filecaps.fc_nioctls != -1) {
3005 ndp->ni_lcf |= NI_LCF_STRICTRELATIVE;
3017 const struct fdescenttbl *fdt;
3018 struct filedesc *fdp;
3022 VFS_SMR_ASSERT_ENTERED();
3024 fdp = curproc->p_fd;
3025 fdt = fdp->fd_files;
3026 if (__predict_false((u_int)
fd >= fdt->fdt_nfiles))
3028 fp = fdt->fdt_ofiles[
fd].fde_file;
3029 if (__predict_false(fp == NULL))
3031 *fsearch = ((fp->f_flag & FSEARCH) != 0);
3033 if (__predict_false(vp == NULL || vp->v_type != VDIR)) {
3040 atomic_thread_fence_acq();
3041 fdt = fdp->fd_files;
3042 if (__predict_false(fp != fdt->fdt_ofiles[
fd].fde_file))
3065 struct file **fpp, seqc_t *seqp)
3067 struct filedesc *fdp;
3068 const struct filedescent *fde;
3069 const struct fdescenttbl *fdt;
3072 cap_rights_t haverights;
3075 fdp = td->td_proc->p_fd;
3076 fdt = fdp->fd_files;
3077 if (__predict_false((u_int)
fd >= fdt->fdt_nfiles))
3081 seq = seqc_read_notmodify(fd_seqc(fdt,
fd));
3082 fde = &fdt->fdt_ofiles[
fd];
3083 haverights = *cap_rights_fde_inline(fde);
3085 if (__predict_false(fp == NULL)) {
3086 if (seqc_consistent(fd_seqc(fdt,
fd), seq))
3088 fdt = atomic_load_ptr(&fdp->fd_files);
3091 error = cap_check_inline(&haverights, needrightsp);
3092 if (__predict_false(error != 0)) {
3093 if (seqc_consistent(fd_seqc(fdt,
fd), seq))
3095 fdt = atomic_load_ptr(&fdp->fd_files);
3098 if (__predict_false(!refcount_acquire_if_not_zero(&fp->f_count))) {
3099 fdt = atomic_load_ptr(&fdp->fd_files);
3106 atomic_thread_fence_acq();
3107 fdt = fdp->fd_files;
3108 if (seqc_consistent_no_fence(fd_seqc(fdt,
fd), seq))
3121 struct file **fpp, seqc_t *seqp __unused)
3123 struct filedesc *fdp;
3124 const struct fdescenttbl *fdt;
3127 fdp = td->td_proc->p_fd;
3128 fdt = fdp->fd_files;
3129 if (__predict_false((u_int)
fd >= fdt->fdt_nfiles))
3133 fp = fdt->fdt_ofiles[
fd].fde_file;
3134 if (__predict_false(fp == NULL))
3136 if (__predict_false(!refcount_acquire_if_not_zero(&fp->f_count))) {
3137 fdt = atomic_load_ptr(&fdp->fd_files);
3144 atomic_thread_fence_acq();
3145 fdt = fdp->fd_files;
3146 if (__predict_true(fp == fdt->fdt_ofiles[
fd].fde_file))
3166 struct filedesc *fdp;
3168 const struct filedescent *fde;
3170 const struct fdescenttbl *fdt;
3174 const cap_rights_t *haverights;
3177 fdp = td->td_proc->p_fd;
3178 fdt = fdp->fd_files;
3179 if (__predict_false((u_int)
fd >= fdt->fdt_nfiles)) {
3184 seq = seqc_read_notmodify(fd_seqc(fdt,
fd));
3185 fde = &fdt->fdt_ofiles[
fd];
3186 haverights = cap_rights_fde_inline(fde);
3189 fp = fdt->fdt_ofiles[
fd].fde_file;
3191 if (__predict_false(fp == NULL))
3194 if (__predict_false(cap_check_inline_transient(haverights, needrightsp)))
3197 if (__predict_false(!refcount_acquire_if_not_zero(&fp->f_count)))
3204 atomic_thread_fence_acq();
3205 fdt = fdp->fd_files;
3207 if (__predict_false(!seqc_consistent_no_fence(fd_seqc(fdt,
fd), seq)))
3209 if (__predict_false(fp != fdt->fdt_ofiles[
fd].fde_file))
3235 const struct filedescent *fde;
3236 const struct fdescenttbl *fdt;
3237 const cap_rights_t *haverights;
3241 MPASS(FILEDESC_IS_ONLY_USER(fdp));
3244 if (__predict_false(
fd >= fdp->fd_nfiles))
3247 fdt = fdp->fd_files;
3248 fde = &fdt->fdt_ofiles[
fd];
3250 if (__predict_false(fp == NULL))
3252 MPASS(refcount_load(&fp->f_count) > 0);
3253 haverights = cap_rights_fde_inline(fde);
3254 error = cap_check_inline(haverights, needrightsp);
3255 if (__predict_false(error != 0))
3267 MPASS(FILEDESC_IS_ONLY_USER(fdp));
3270 if (__predict_false(
fd >= fdp->fd_nfiles))
3273 fp = fdp->fd_ofiles[
fd].fde_file;
3274 if (__predict_false(fp == NULL))
3277 MPASS(refcount_load(&fp->f_count) > 0);
3298 cap_rights_t *needrightsp)
3305 if (__predict_false(error != 0))
3307 if (__predict_false(fp->f_ops == &
badfileops)) {
3319 if ((fp->f_flag &
flags) == 0)
3324 ((fp->f_flag & (FREAD | FEXEC)) == 0 ||
3325 (fp->f_flag & FWRITE) != 0))
3331 KASSERT(0, (
"wrong flags"));
3344fget(
struct thread *td,
int fd, cap_rights_t *rightsp,
struct file **fpp)
3347 return (
_fget(td,
fd, fpp, 0, rightsp));
3351fget_mmap(
struct thread *td,
int fd, cap_rights_t *rightsp, vm_prot_t *maxprotp,
3356 error =
_fget(td,
fd, fpp, 0, rightsp);
3357 if (maxprotp != NULL)
3358 *maxprotp = VM_PROT_ALL;
3361 cap_rights_t fdrights;
3362 struct filedesc *fdp;
3367 fdp = td->td_proc->p_fd;
3368 MPASS(cap_rights_is_set(rightsp, CAP_MMAP));
3371 if (__predict_false(error != 0))
3373 if (__predict_false(fp->f_ops == &
badfileops)) {
3377 if (maxprotp != NULL)
3378 fdrights = *cap_rights(fdp,
fd);
3379 if (!fd_modified(fdp,
fd, seq))
3387 if (maxprotp != NULL)
3388 *maxprotp = cap_rights_to_vmprot(&fdrights);
3395fget_read(
struct thread *td,
int fd, cap_rights_t *rightsp,
struct file **fpp)
3398 return (
_fget(td,
fd, fpp, FREAD, rightsp));
3402fget_write(
struct thread *td,
int fd, cap_rights_t *rightsp,
struct file **fpp)
3405 return (
_fget(td,
fd, fpp, FWRITE, rightsp));
3415 struct filedesc *fdp = td->td_proc->p_fd;
3421 MPASS(cap_rights_is_set(rightsp, CAP_FCNTL));
3426 error = cap_fcntl_check(fdp,
fd, needfcntl);
3427 if (!fd_modified(fdp,
fd, seq))
3458 if (fp->f_vnode == NULL) {
3470fgetvp(
struct thread *td,
int fd, cap_rights_t *rightsp,
struct vnode **vpp)
3473 return (
_fgetvp(td,
fd, 0, rightsp, vpp));
3478 struct filecaps *havecaps,
struct vnode **vpp)
3480 struct filecaps caps;
3484 error =
fget_cap(td,
fd, needrightsp, &fp, &caps);
3491 if (fp->f_vnode == NULL) {
3509fgetvp_read(
struct thread *td,
int fd, cap_rights_t *rightsp,
struct vnode **vpp)
3512 return (
_fgetvp(td,
fd, FREAD, rightsp, vpp));
3516fgetvp_exec(
struct thread *td,
int fd, cap_rights_t *rightsp,
struct vnode **vpp)
3519 return (
_fgetvp(td,
fd, FEXEC, rightsp, vpp));
3524fgetvp_write(
struct thread *td,
int fd, cap_rights_t *rightsp,
3528 return (
_fgetvp(td,
fd, FWRITE, rightsp, vpp));
3545 count = refcount_load(&fp->f_count);
3549 error = fo_close(fp, td);
3552 free(fp->f_advice, M_FADVISE);
3564#ifndef _SYS_SYSPROTO_H_
3583 if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) {
3592 lf.l_whence = SEEK_SET;
3595 if (uap->
how & LOCK_UN) {
3596 lf.l_type = F_UNLCK;
3597 atomic_clear_int(&fp->f_flag, FHASLOCK);
3598 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
3601 if (uap->
how & LOCK_EX)
3602 lf.l_type = F_WRLCK;
3603 else if (uap->
how & LOCK_SH)
3604 lf.l_type = F_RDLCK;
3609 atomic_set_int(&fp->f_flag, FHASLOCK);
3610 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
3611 (uap->
how & LOCK_NB) ? F_FLOCK : F_FLOCK | F_WAIT);
3621 int openerror,
int *indxp)
3623 struct filedescent *newfde, *oldfde;
3628 KASSERT(openerror == ENODEV || openerror == ENXIO,
3629 (
"unexpected error %d in %s", openerror, __func__));
3636 FILEDESC_XLOCK(fdp);
3637 if ((fp = fget_noref(fdp, dfd)) == NULL) {
3638 FILEDESC_XUNLOCK(fdp);
3642 error =
fdalloc(td, 0, &indx);
3644 FILEDESC_XUNLOCK(fdp);
3656 switch (openerror) {
3662 if (((
mode & (FREAD|FWRITE)) | fp->f_flag) != fp->f_flag) {
3664 FILEDESC_XUNLOCK(fdp);
3669 FILEDESC_XUNLOCK(fdp);
3672 newfde = &fdp->fd_ofiles[indx];
3673 oldfde = &fdp->fd_ofiles[dfd];
3676 seqc_write_begin(&newfde->fde_seqc);
3678 fde_copy(oldfde, newfde);
3682 seqc_write_end(&newfde->fde_seqc);
3689 newfde = &fdp->fd_ofiles[indx];
3690 oldfde = &fdp->fd_ofiles[dfd];
3692 seqc_write_begin(&oldfde->fde_seqc);
3693 seqc_write_begin(&newfde->fde_seqc);
3695 fde_copy(oldfde, newfde);
3696 oldfde->fde_file = NULL;
3699 seqc_write_end(&newfde->fde_seqc);
3700 seqc_write_end(&oldfde->fde_seqc);
3704 FILEDESC_XUNLOCK(fdp);
3721 "Allow a process to chroot(2) if it has a directory open");
3734 FILEDESC_LOCK_ASSERT(fdp);
3737 if (fp->f_type == DTYPE_VNODE) {
3739 if (vp->v_type == VDIR)
3750 if (newpwd->pwd_cdir == NULL && oldpwd->pwd_cdir != NULL) {
3752 newpwd->pwd_cdir = oldpwd->pwd_cdir;
3755 if (newpwd->pwd_rdir == NULL && oldpwd->pwd_rdir != NULL) {
3757 newpwd->pwd_rdir = oldpwd->pwd_rdir;
3760 if (newpwd->pwd_jdir == NULL && oldpwd->pwd_jdir != NULL) {
3762 newpwd->pwd_jdir = oldpwd->pwd_jdir;
3771 PWDDESC_ASSERT_XLOCKED(pdp);
3772 pwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
3774 refcount_acquire(&pwd->pwd_refcount);
3783 if (__predict_true(refcount_acquire_if_not_zero(&pwd->pwd_refcount))) {
3792 struct pwddesc *pdp;
3795 pdp = td->td_proc->p_pd;
3798 pwd = vfs_smr_entered_load(&pdp->pd_pwd);
3807 PWDDESC_XUNLOCK(pdp);
3814 struct pwddesc *pdp;
3817 PROC_ASSERT_HELD(p);
3826 PWDDESC_XUNLOCK(pdp);
3836 pwd = uma_zalloc_smr(
pwd_zone, M_WAITOK);
3837 bzero(pwd,
sizeof(*pwd));
3838 refcount_init(&pwd->pwd_refcount, 1);
3846 if (!refcount_release(&pwd->pwd_refcount))
3849 if (pwd->pwd_cdir != NULL)
3850 vrele(pwd->pwd_cdir);
3851 if (pwd->pwd_rdir != NULL)
3852 vrele(pwd->pwd_rdir);
3853 if (pwd->pwd_jdir != NULL)
3854 vrele(pwd->pwd_jdir);
3865 struct pwddesc *pdp;
3866 struct filedesc *fdp;
3867 struct pwd *newpwd, *oldpwd;
3870 fdp = td->td_proc->p_fd;
3871 pdp = td->td_proc->p_pd;
3873 FILEDESC_SLOCK(fdp);
3875 oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
3880 FILEDESC_SUNLOCK(fdp);
3882 PWDDESC_XUNLOCK(pdp);
3887 FILEDESC_SUNLOCK(fdp);
3891 newpwd->pwd_rdir = vp;
3892 if (oldpwd->pwd_jdir == NULL) {
3894 newpwd->pwd_jdir = vp;
3897 pwd_set(pdp, newpwd);
3898 PWDDESC_XUNLOCK(pdp);
3906 struct pwddesc *pdp;
3907 struct pwd *newpwd, *oldpwd;
3909 VNPASS(vp->v_usecount > 0, vp);
3912 pdp = td->td_proc->p_pd;
3914 oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
3915 newpwd->pwd_cdir = vp;
3917 pwd_set(pdp, newpwd);
3918 PWDDESC_XUNLOCK(pdp);
3928 struct pwddesc *pdp;
3929 struct filedesc *fdp;
3930 struct pwd *newpwd, *oldpwd;
3933 fdp = td->td_proc->p_fd;
3934 pdp = td->td_proc->p_pd;
3936 FILEDESC_SLOCK(fdp);
3938 oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
3940 FILEDESC_SUNLOCK(fdp);
3942 PWDDESC_XUNLOCK(pdp);
3948 newpwd->pwd_rdir = vp;
3950 newpwd->pwd_cdir = vp;
3951 if (oldpwd->pwd_jdir == NULL) {
3953 newpwd->pwd_jdir = vp;
3956 pwd_set(pdp, newpwd);
3957 PWDDESC_XUNLOCK(pdp);
3965 struct pwddesc *pdp;
3966 struct pwd *oldpwd, *newpwd;
3968 pdp = curproc->p_pd;
3970 oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
3971 if (oldpwd->pwd_cdir != NULL && oldpwd->pwd_rdir != NULL) {
3972 PWDDESC_XUNLOCK(pdp);
3975 PWDDESC_XUNLOCK(pdp);
3979 oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
3981 if (newpwd->pwd_cdir == NULL) {
3985 if (newpwd->pwd_rdir == NULL) {
3989 pwd_set(pdp, newpwd);
3990 PWDDESC_XUNLOCK(pdp);
3997 struct pwddesc *pdp;
3998 struct pwd *oldpwd, *newpwd;
4000 pdp = curproc->p_pd;
4004 oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
4010 pwd_set(pdp, newpwd);
4011 PWDDESC_XUNLOCK(pdp);
4022 struct pwddesc *pdp;
4023 struct pwd *newpwd, *oldpwd;
4028 if (vrefcnt(olddp) == 1)
4033 FOREACH_PROC_IN_SYSTEM(p) {
4040 oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
4041 if (oldpwd == NULL ||
4042 (oldpwd->pwd_cdir != olddp &&
4043 oldpwd->pwd_rdir != olddp &&
4044 oldpwd->pwd_jdir != olddp)) {
4045 PWDDESC_XUNLOCK(pdp);
4049 if (oldpwd->pwd_cdir == olddp) {
4051 newpwd->pwd_cdir = newdp;
4053 if (oldpwd->pwd_rdir == olddp) {
4055 newpwd->pwd_rdir = newdp;
4057 if (oldpwd->pwd_jdir == olddp) {
4059 newpwd->pwd_jdir = newdp;
4062 pwd_set(pdp, newpwd);
4063 PWDDESC_XUNLOCK(pdp);
4076 if (
prison0.pr_root == olddp) {
4084 mtx_lock(&
pr->pr_mtx);
4085 if (
pr->pr_root == olddp) {
4087 pr->pr_root = newdp;
4090 mtx_unlock(&
pr->pr_mtx);
4097struct filedesc_to_leader *
4100 struct filedesc_to_leader *fdtol;
4102 fdtol =
malloc(
sizeof(
struct filedesc_to_leader),
4103 M_FILEDESC_TO_LEADER, M_WAITOK);
4104 fdtol->fdl_refcount = 1;
4105 fdtol->fdl_holdcount = 0;
4106 fdtol->fdl_wakeup = 0;
4107 fdtol->fdl_leader = leader;
4109 FILEDESC_XLOCK(fdp);
4110 fdtol->fdl_next = old->fdl_next;
4111 fdtol->fdl_prev = old;
4112 old->fdl_next = fdtol;
4113 fdtol->fdl_next->fdl_prev = fdtol;
4114 FILEDESC_XUNLOCK(fdp);
4116 fdtol->fdl_next = fdtol;
4117 fdtol->fdl_prev = fdtol;
4126 struct filedesc *fdp;
4128 int count, off, minoff;
4134 if (*(
int *)arg1 != 0)
4137 fdp = curproc->p_fd;
4139 FILEDESC_SLOCK(fdp);
4141 off =
NDSLOT(fdp->fd_nfiles - 1);
4142 for (minoff =
NDSLOT(0); off >= minoff; --off)
4143 count += bitcountl(map[off]);
4144 FILEDESC_SUNLOCK(fdp);
4146 return (SYSCTL_OUT(req, &
count,
sizeof(
count)));
4151 "Number of open file descriptors");
4160 struct filedesc *fdp;
4168 if (req->oldptr == NULL) {
4171 FOREACH_PROC_IN_SYSTEM(p) {
4173 if (p->p_state == PRS_NEW) {
4182 n += fdp->fd_nfiles;
4186 return (SYSCTL_OUT(req, 0, n *
sizeof(xf)));
4189 bzero(&xf,
sizeof(xf));
4190 xf.xf_size =
sizeof(xf);
4192 FOREACH_PROC_IN_SYSTEM(p) {
4194 if (p->p_state == PRS_NEW) {
4202 xf.xf_pid = p->p_pid;
4203 xf.xf_uid = p->p_ucred->cr_uid;
4208 FILEDESC_SLOCK(fdp);
4209 if (refcount_load(&fdp->fd_refcnt) == 0)
4213 xf.xf_file = (uintptr_t)fp;
4214 xf.xf_data = (uintptr_t)fp->f_data;
4215 xf.xf_vnode = (uintptr_t)fp->f_vnode;
4216 xf.xf_type = (uintptr_t)fp->f_type;
4217 xf.xf_count = refcount_load(&fp->f_count);
4219 xf.xf_offset = foffset_get(fp);
4220 xf.xf_flag = fp->f_flag;
4221 error = SYSCTL_OUT(req, &xf,
sizeof(xf));
4232 FILEDESC_SUNLOCK(fdp);
4241SYSCTL_PROC(_kern, KERN_FILE, file, CTLTYPE_OPAQUE|CTLFLAG_RD|CTLFLAG_MPSAFE,
4244#ifdef KINFO_FILE_SIZE
4245CTASSERT(
sizeof(
struct kinfo_file) == KINFO_FILE_SIZE);
4251 static const struct {
4254 } fflags_table[] = {
4255 { FAPPEND, KF_FLAG_APPEND },
4256 { FASYNC, KF_FLAG_ASYNC },
4257 { FFSYNC, KF_FLAG_FSYNC },
4258 { FHASLOCK, KF_FLAG_HASLOCK },
4259 { FNONBLOCK, KF_FLAG_NONBLOCK },
4260 { FREAD, KF_FLAG_READ },
4261 { FWRITE, KF_FLAG_WRITE },
4262 { O_CREAT, KF_FLAG_CREAT },
4263 { O_DIRECT, KF_FLAG_DIRECT },
4264 { O_EXCL, KF_FLAG_EXCL },
4265 { O_EXEC, KF_FLAG_EXEC },
4266 { O_EXLOCK, KF_FLAG_EXLOCK },
4267 { O_NOFOLLOW, KF_FLAG_NOFOLLOW },
4268 { O_SHLOCK, KF_FLAG_SHLOCK },
4269 { O_TRUNC, KF_FLAG_TRUNC }
4275 for (i = 0; i < nitems(fflags_table); i++)
4276 if (fflags & fflags_table[i].fflag)
4277 kflags |= fflags_table[i].kf_fflag;
4286 kif->kf_structsize = offsetof(
struct kinfo_file, kf_path) +
4287 strlen(kif->kf_path) + 1;
4288 kif->kf_structsize = roundup(kif->kf_structsize,
sizeof(uint64_t));
4293 struct kinfo_file *kif,
struct filedesc *fdp,
int flags)
4297 bzero(kif,
sizeof(*kif));
4300 kif->kf_type = KF_TYPE_UNKNOWN;
4302 if (rightsp != NULL)
4303 kif->kf_cap_rights = *rightsp;
4305 cap_rights_init_zero(&kif->kf_cap_rights);
4307 kif->kf_ref_count = refcount_load(&fp->f_count);
4308 kif->kf_offset = foffset_get(fp);
4314 error = fo_fill_kinfo(fp, kif, fdp);
4316 kif->kf_status |= KF_ATTR_VALID;
4317 if ((
flags & KERN_FILEDESC_PACK_KINFO) != 0)
4320 kif->kf_structsize = roundup2(
sizeof(*kif),
sizeof(uint64_t));
4325 struct kinfo_file *kif,
int flags)
4329 bzero(kif,
sizeof(*kif));
4331 kif->kf_type = KF_TYPE_VNODE;
4334 kif->kf_status |= KF_ATTR_VALID;
4336 cap_rights_init_zero(&kif->kf_cap_rights);
4338 kif->kf_ref_count = -1;
4339 kif->kf_offset = -1;
4340 if ((
flags & KERN_FILEDESC_PACK_KINFO) != 0)
4343 kif->kf_structsize = roundup2(
sizeof(*kif),
sizeof(uint64_t));
4359 struct kinfo_file *kif;
4363 if (efbuf->
remainder < kif->kf_structsize)
4367 if (
sbuf_bcat(efbuf->
sb, kif, kif->kf_structsize) != 0)
4382 FILEDESC_SUNLOCK(efbuf->
fdp);
4384 FILEDESC_SLOCK(efbuf->
fdp);
4396 if (efbuf->
pdp != NULL)
4397 PWDDESC_XUNLOCK(efbuf->
pdp);
4400 if (efbuf->
pdp != NULL)
4401 PWDDESC_XLOCK(efbuf->
pdp);
4415 struct filedesc *fdp;
4416 struct pwddesc *pdp;
4418 struct vnode *cttyvp, *textvp, *tracevp;
4421 cap_rights_t rights;
4423 PROC_LOCK_ASSERT(p, MA_OWNED);
4426 tracevp = ktr_get_tracevp(p,
true);
4428 textvp = p->p_textvp;
4433 if (p->p_pgrp != NULL && p->p_pgrp->pg_session != NULL) {
4434 cttyvp = p->p_pgrp->pg_session->s_ttyvp;
4442 efbuf =
malloc(
sizeof(*efbuf), M_TEMP, M_WAITOK);
4450 if (tracevp != NULL)
4452 FREAD | FWRITE, efbuf);
4453 if (error == 0 && textvp != NULL)
4456 if (error == 0 && cttyvp != NULL)
4458 FREAD | FWRITE, efbuf);
4459 if (error != 0 || pdp == NULL || fdp == NULL)
4467 if (pwd->pwd_cdir != NULL) {
4470 KF_FD_TYPE_CWD, FREAD, efbuf);
4473 if (error == 0 && pwd->pwd_rdir != NULL) {
4476 KF_FD_TYPE_ROOT, FREAD, efbuf);
4479 if (error == 0 && pwd->pwd_jdir != NULL) {
4482 KF_FD_TYPE_JAIL, FREAD, efbuf);
4485 PWDDESC_XUNLOCK(pdp);
4490 FILEDESC_SLOCK(fdp);
4491 if (refcount_load(&fdp->fd_refcnt) == 0)
4495 rights = *cap_rights(fdp, i);
4506 if (error != 0 || refcount_load(&fdp->fd_refcnt) == 0)
4510 FILEDESC_SUNLOCK(fdp);
4516 free(efbuf, M_TEMP);
4520#define FILEDESC_SBUF_SIZE (sizeof(struct kinfo_file) * 5)
4532 int error, error2, *
name;
4542 error =
pget((pid_t)
name[0], PGET_CANDEBUG | PGET_NOTWEXIT, &p);
4547 maxlen = req->oldptr != NULL ? req->oldlen : -1;
4549 KERN_FILEDESC_PACK_KINFO);
4552 return (error != 0 ? error : error2);
4555#ifdef COMPAT_FREEBSD7
4556#ifdef KINFO_OFILE_SIZE
4557CTASSERT(
sizeof(
struct kinfo_ofile) == KINFO_OFILE_SIZE);
4561kinfo_to_okinfo(
struct kinfo_file *kif,
struct kinfo_ofile *okif)
4564 okif->kf_structsize =
sizeof(*okif);
4565 okif->kf_type = kif->kf_type;
4566 okif->kf_fd = kif->kf_fd;
4567 okif->kf_ref_count = kif->kf_ref_count;
4568 okif->kf_flags = kif->kf_flags & (KF_FLAG_READ | KF_FLAG_WRITE |
4569 KF_FLAG_APPEND | KF_FLAG_ASYNC | KF_FLAG_FSYNC | KF_FLAG_NONBLOCK |
4570 KF_FLAG_DIRECT | KF_FLAG_HASLOCK);
4571 okif->kf_offset = kif->kf_offset;
4572 if (kif->kf_type == KF_TYPE_VNODE)
4573 okif->kf_vnode_type = kif->kf_un.kf_file.kf_file_type;
4575 okif->kf_vnode_type = KF_VTYPE_VNON;
4576 strlcpy(okif->kf_path, kif->kf_path,
sizeof(okif->kf_path));
4577 if (kif->kf_type == KF_TYPE_SOCKET) {
4578 okif->kf_sock_domain = kif->kf_un.kf_sock.kf_sock_domain0;
4579 okif->kf_sock_type = kif->kf_un.kf_sock.kf_sock_type0;
4580 okif->kf_sock_protocol = kif->kf_un.kf_sock.kf_sock_protocol0;
4581 okif->kf_sa_local = kif->kf_un.kf_sock.kf_sa_local;
4582 okif->kf_sa_peer = kif->kf_un.kf_sock.kf_sa_peer;
4584 okif->kf_sa_local.ss_family = AF_UNSPEC;
4585 okif->kf_sa_peer.ss_family = AF_UNSPEC;
4590export_vnode_for_osysctl(
struct vnode *vp,
int type,
struct kinfo_file *kif,
4591 struct kinfo_ofile *okif,
struct pwddesc *pdp,
struct sysctl_req *req)
4596 PWDDESC_XUNLOCK(pdp);
4598 kinfo_to_okinfo(kif, okif);
4599 error = SYSCTL_OUT(req, okif,
sizeof(*okif));
4608sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS)
4610 struct kinfo_ofile *okif;
4611 struct kinfo_file *kif;
4612 struct filedesc *fdp;
4613 struct pwddesc *pdp;
4616 int error, i, *
name;
4625 error =
pget((pid_t)
name[0], PGET_CANDEBUG | PGET_NOTWEXIT, &p);
4632 if (fdp == NULL || pdp == NULL) {
4637 kif =
malloc(
sizeof(*kif), M_TEMP, M_WAITOK);
4638 okif =
malloc(
sizeof(*okif), M_TEMP, M_WAITOK);
4642 if (pwd->pwd_cdir != NULL)
4643 export_vnode_for_osysctl(pwd->pwd_cdir, KF_FD_TYPE_CWD, kif,
4645 if (pwd->pwd_rdir != NULL)
4646 export_vnode_for_osysctl(pwd->pwd_rdir, KF_FD_TYPE_ROOT, kif,
4648 if (pwd->pwd_jdir != NULL)
4649 export_vnode_for_osysctl(pwd->pwd_jdir, KF_FD_TYPE_JAIL, kif,
4652 PWDDESC_XUNLOCK(pdp);
4655 FILEDESC_SLOCK(fdp);
4656 if (refcount_load(&fdp->fd_refcnt) == 0)
4660 KERN_FILEDESC_PACK_KINFO);
4661 FILEDESC_SUNLOCK(fdp);
4662 kinfo_to_okinfo(kif, okif);
4663 error = SYSCTL_OUT(req, okif,
sizeof(*okif));
4664 FILEDESC_SLOCK(fdp);
4665 if (error != 0 || refcount_load(&fdp->fd_refcnt) == 0)
4669 FILEDESC_SUNLOCK(fdp);
4677static SYSCTL_NODE(_kern_proc, KERN_PROC_OFILEDESC, ofiledesc,
4678 CTLFLAG_RD|CTLFLAG_MPSAFE, sysctl_kern_proc_ofiledesc,
4679 "Process ofiledesc entries");
4688 } vtypes_table[] = {
4689 { VBAD, KF_VTYPE_VBAD },
4690 { VBLK, KF_VTYPE_VBLK },
4691 { VCHR, KF_VTYPE_VCHR },
4692 { VDIR, KF_VTYPE_VDIR },
4693 { VFIFO, KF_VTYPE_VFIFO },
4694 { VLNK, KF_VTYPE_VLNK },
4695 { VNON, KF_VTYPE_VNON },
4696 { VREG, KF_VTYPE_VREG },
4697 { VSOCK, KF_VTYPE_VSOCK }
4704 for (i = 0; i < nitems(vtypes_table); i++)
4705 if (vtypes_table[i].vtype == vtype)
4706 return (vtypes_table[i].kf_vtype);
4708 return (KF_VTYPE_UNKNOWN);
4713 "Process filedesc entries");
4723 struct pwddesc *pdp;
4729 PROC_LOCK_ASSERT(p, MA_OWNED);
4736 efbuf =
malloc(
sizeof(*efbuf), M_TEMP, M_WAITOK);
4744 pwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
4745 cdir = pwd->pwd_cdir;
4752 PWDDESC_XUNLOCK(pdp);
4754 free(efbuf, M_TEMP);
4768 int error, error2, *
name;
4778 error =
pget((pid_t)
name[0], PGET_CANDEBUG | PGET_NOTWEXIT, &p);
4783 maxlen = req->oldptr != NULL ? req->oldlen : -1;
4787 return (error != 0 ? error : error2);
4790static SYSCTL_NODE(_kern_proc, KERN_PROC_CWD, cwd, CTLFLAG_RD|CTLFLAG_MPSAFE,
4799file_type_to_name(
short type)
4827 case DTYPE_PROCDESC:
4831 case DTYPE_LINUXTFD:
4844file_to_first_proc(
struct file *fp)
4846 struct filedesc *fdp;
4850 FOREACH_PROC_IN_SYSTEM(p) {
4851 if (p->p_state == PRS_NEW)
4856 for (n = 0; n < fdp->fd_nfiles; n++) {
4857 if (fp == fdp->fd_ofiles[n].fde_file)
4865db_print_file(
struct file *fp,
int header)
4867#define XPTRWIDTH ((int)howmany(sizeof(void *) * NBBY, 4))
4871 db_printf(
"%*s %6s %*s %8s %4s %5s %6s %*s %5s %s\n",
4872 XPTRWIDTH,
"File",
"Type", XPTRWIDTH,
"Data",
"Flag",
4873 "GCFl",
"Count",
"MCount", XPTRWIDTH,
"Vnode",
"FPID",
4875 p = file_to_first_proc(fp);
4876 db_printf(
"%*p %6s %*p %08x %04x %5d %6d %*p %5d %s\n", XPTRWIDTH,
4877 fp, file_type_to_name(fp->f_type), XPTRWIDTH, fp->f_data,
4878 fp->f_flag, 0, refcount_load(&fp->f_count), 0, XPTRWIDTH, fp->f_vnode,
4879 p != NULL ? p->p_pid : -1, p != NULL ? p->p_comm :
"-");
4884DB_SHOW_COMMAND(file, db_show_file)
4889 db_printf(
"usage: show file <addr>\n");
4892 fp = (
struct file *)
addr;
4893 db_print_file(fp, 1);
4896DB_SHOW_COMMAND(files, db_show_files)
4898 struct filedesc *fdp;
4905 FOREACH_PROC_IN_SYSTEM(p) {
4906 if (p->p_state == PRS_NEW)
4908 if ((fdp = p->p_fd) == NULL)
4910 for (n = 0; n < fdp->fd_nfiles; ++n) {
4911 if ((fp = fdp->fd_ofiles[n].fde_file) == NULL)
4913 db_print_file(fp, header);
4924 &
maxfiles, 0,
"Maximum number of files");
4927 &
openfiles, 0,
"System-wide number of open files");
4934 file_zone = uma_zcreate(
"Files",
sizeof(
struct file), NULL, NULL,
4935 NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
4937 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
4938 pwd_zone = uma_zcreate(
"PWD",
sizeof(
struct pwd), NULL, NULL,
4939 NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_SMR);
4944 vfs_smr = uma_zone_get_smr(
pwd_zone);
4945 mtx_init(&
sigio_lock,
"sigio lock", NULL, MTX_DEF);
4953 int flags,
struct thread *td)
4976badfo_poll(
struct file *fp,
int events,
struct ucred *active_cred,
4991badfo_stat(
struct file *fp,
struct stat *sb,
struct ucred *active_cred)
5013badfo_chown(
struct file *fp, uid_t uid, gid_t gid,
struct ucred *active_cred,
5022 struct uio *trl_uio, off_t offset,
size_t nbytes, off_t *sent,
int flags,
5052path_poll(
struct file *fp,
int events,
struct ucred *active_cred,
5061 MPASS(fp->f_type == DTYPE_VNODE);
5080 .fo_flags = DFLAG_PASSABLE,
5084invfo_rdwr(
struct file *fp,
struct uio *uio,
struct ucred *active_cred,
5085 int flags,
struct thread *td)
5088 return (EOPNOTSUPP);
5101 struct ucred *active_cred,
struct thread *td)
5108invfo_poll(
struct file *fp,
int events,
struct ucred *active_cred,
5131invfo_chown(
struct file *fp, uid_t uid, gid_t gid,
struct ucred *active_cred,
5140 struct uio *trl_uio, off_t offset,
size_t nbytes, off_t *sent,
int flags,
5173 td->td_dupfd = dev2unit(dev);
5178 .d_version = D_VERSION,
5189 UID_ROOT, GID_WHEEL, 0666,
"fd/0");
5192 UID_ROOT, GID_WHEEL, 0666,
"fd/1");
5195 UID_ROOT, GID_WHEEL, 0666,
"fd/2");
device_property_type_t type
CTASSERT(MAXSHELLCMDLEN >=MAXINTERP+3)
struct cdev * make_dev_credf(int flags, struct cdevsw *devsw, int unit, struct ucred *cr, uid_t uid, gid_t gid, int mode, const char *fmt,...)
struct cdev * make_dev_alias(struct cdev *pdev, const char *fmt,...)
struct pwd * pwd_hold(struct thread *td)
int sys_fpathconf(struct thread *td, struct fpathconf_args *uap)
static u_long * filecaps_copy_prep(const struct filecaps *src)
static int badfo_poll(struct file *fp, int events, struct ucred *active_cred, struct thread *td)
int fget_cap_noref(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, struct file **fpp, struct filecaps *havecapsp)
void pdescfree(struct thread *td)
static void fdescfree_fds(struct thread *td, struct filedesc *fdp)
int fgetvp(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp)
int fgetvp_read(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp)
int fdcheckstd(struct thread *td)
static int __exclusive_cache_line openfiles
static int badfo_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio, struct uio *trl_uio, off_t offset, size_t nbytes, off_t *sent, int flags, struct thread *td)
static void filecaps_fill(struct filecaps *fcaps)
static int badfo_kqfilter(struct file *fp, struct knote *kn)
int invfo_ioctl(struct file *fp, u_long com, void *data, struct ucred *active_cred, struct thread *td)
bool pwd_hold_smr(struct pwd *pwd)
void filecaps_move(struct filecaps *src, struct filecaps *dst)
int kern_dup(struct thread *td, u_int mode, int flags, int old, int new)
static void fdfree(struct filedesc *fdp, int fd)
static void sigiofree(struct sigio *sigio)
void _finstall(struct filedesc *fdp, struct file *fp, int fd, int flags, struct filecaps *fcaps)
int invfo_truncate(struct file *fp, off_t length, struct ucred *active_cred, struct thread *td)
int finstall(struct thread *td, struct file *fp, int *fd, int flags, struct filecaps *fcaps)
static int export_kinfo_to_sb(struct export_fd_buf *efbuf)
static struct pwddesc * pdhold(struct proc *p)
static int badfo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
static int badfo_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred, struct thread *td)
static void fddrop(struct filedesc *fdp)
void pwd_chdir(struct thread *td, struct vnode *vp)
void __read_mostly(* mq_fdclose)(struct thread *td, int fd, struct file *fp)
bool filecaps_copy(const struct filecaps *src, struct filecaps *dst, bool locked)
struct filedesc * fdshare(struct filedesc *fdp)
void pwd_drop(struct pwd *pwd)
static int fdopen(struct cdev *dev, int mode, int type, struct thread *td)
static void filecaps_validate(const struct filecaps *fcaps, const char *func)
int fget_write(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp)
static int closefp(struct filedesc *fdp, int fd, struct file *fp, struct thread *td, bool holdleaders, bool audit)
void falloc_abort(struct thread *td, struct file *fp)
int kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen, int flags)
void closef_nothread(struct file *fp)
int pwd_chroot(struct thread *td, struct vnode *vp)
struct pwd * pwd_hold_pwddesc(struct pwddesc *pdp)
static __inline int _fget(struct thread *td, int fd, struct file **fpp, int flags, cap_rights_t *needrightsp)
int sys_fstat(struct thread *td, struct fstat_args *uap)
static int export_vnode_to_sb(struct vnode *vp, int fd, int fflags, struct export_fd_buf *efbuf)
static int badfo_readwrite(struct file *fp, struct uio *uio, struct ucred *active_cred, int flags, struct thread *td)
struct pwddesc * pdinit(struct pwddesc *pdp, bool keeplock)
MALLOC_DECLARE(M_FADVISE)
int sys_dup(struct thread *td, struct dup_args *uap)
int fsetown(pid_t pgid, struct sigio **sigiop)
struct pwddesc * pdshare(struct pwddesc *pdp)
void mountcheckdirs(struct vnode *olddp, struct vnode *newdp)
int _falloc_noinstall(struct thread *td, struct file **resultfp, u_int n)
int invfo_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred, struct thread *td)
struct filedesc * fdcopy(struct filedesc *fdp)
static void fdused_init(struct filedesc *fdp, int fd)
static int chroot_allow_open_directories
static int fdisused(struct filedesc *fdp, int fd)
static int path_poll(struct file *fp, int events, struct ucred *active_cred, struct thread *td)
static int sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
static void fdclearlocks(struct thread *td)
SYSCTL_PROC(_kern, KERN_FILE, file, CTLTYPE_OPAQUE|CTLFLAG_RD|CTLFLAG_MPSAFE, 0, 0, sysctl_kern_file, "S,xfile", "Entire file table")
static u_long * filecaps_free_prep(struct filecaps *fcaps)
static int badfo_stat(struct file *fp, struct stat *sb, struct ucred *active_cred)
static __inline int _fgetvp(struct thread *td, int fd, int flags, cap_rights_t *needrightsp, struct vnode **vpp)
void funsetown(struct sigio **sigiop)
void pwd_ensure_dirs(void)
int kern_fpathconf(struct thread *td, int fd, int name, long *valuep)
int fdlastfile(struct filedesc *fdp)
static void fdefree_last(struct filedescent *fde)
static struct pwd * pwd_alloc(void)
struct filedesc * fdinit(void)
void pdunshare(struct thread *td)
int fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp, struct file **fpp, struct filecaps *havecapsp)
#define FILEDESC_FOREACH_FP(fdp, _iterator, _fp)
pid_t fgetown(struct sigio **sigiop)
int sys_flock(struct thread *td, struct flock_args *uap)
static void fdgrowtable_exp(struct filedesc *fdp, int nfd)
int pwd_chroot_chdir(struct thread *td, struct vnode *vp)
int finstall_refed(struct thread *td, struct file *fp, int *fd, int flags, struct filecaps *fcaps)
int __noinline _fdrop(struct file *fp, struct thread *td)
void fdunshare(struct thread *td)
static int close_range_cloexec(struct thread *td, u_int lowfd, u_int highfd)
static struct sigio * funsetown_locked(struct sigio *sigio)
static int badfo_chmod(struct file *fp, mode_t mode, struct ucred *active_cred, struct thread *td)
static void export_file_to_kinfo(struct file *fp, int fd, cap_rights_t *rightsp, struct kinfo_file *kif, struct filedesc *fdp, int flags)
int fget_only_user(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, struct file **fpp)
static void pwd_fill(struct pwd *oldpwd, struct pwd *newpwd)
static void filecaps_free_finish(u_long *ioctls)
static int chroot_refuse_vdir_fds(struct filedesc *fdp)
#define FILEDESC_SBUF_SIZE
int fget_mmap(struct thread *td, int fd, cap_rights_t *rightsp, vm_prot_t *maxprotp, struct file **fpp)
static void fildesc_drvinit(void *unused)
static void filecaps_copy_finish(const struct filecaps *src, struct filecaps *dst, u_long *ioctls)
int vntype_to_kinfo(int vtype)
void fdclose(struct thread *td, struct file *fp, int idx)
static int closefp_impl(struct filedesc *fdp, int fd, struct file *fp, struct thread *td, bool audit)
int fgetvp_exec(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp)
static int badfo_close(struct file *fp, struct thread *td)
struct pwd * pwd_hold_proc(struct proc *p)
static int xlate_fflags(int fflags)
static void fdunused(struct filedesc *fdp, int fd)
int fdallocn(struct thread *td, int minfd, int *fds, int n)
static int badfo_ioctl(struct file *fp, u_long com, void *data, struct ucred *active_cred, struct thread *td)
int closef(struct file *fp, struct thread *td)
void fdsetugidsafety(struct thread *td)
static int sysctl_kern_proc_nfds(SYSCTL_HANDLER_ARGS)
static int fd_first_free(struct filedesc *fdp, int low, int size)
void funsetownlst(struct sigiolst *sigiolst)
int sys_close_range(struct thread *td, struct close_range_args *uap)
void filecaps_free(struct filecaps *fcaps)
void fdcloseexec(struct thread *td)
int kern_close(struct thread *td, int fd)
static SYSCTL_NODE(_kern_proc, KERN_PROC_NFDS, nfds, CTLFLAG_RD|CTLFLAG_CAPRD|CTLFLAG_MPSAFE, sysctl_kern_proc_nfds, "Number of open file descriptors")
SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW, &chroot_allow_open_directories, 0, "Allow a process to chroot(2) if it has a directory open")
static void fdgrowtable(struct filedesc *fdp, int nfd)
int fgetvp_lookup_smr(int fd, struct nameidata *ndp, struct vnode **vpp, bool *fsearch)
int sys_close(struct thread *td, struct close_args *uap)
int sys_fcntl(struct thread *td, struct fcntl_args *uap)
int invfo_poll(struct file *fp, int events, struct ucred *active_cred, struct thread *td)
int fget(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp)
void pack_kinfo(struct kinfo_file *kif)
struct filedesc_to_leader * filedesc_to_leader_alloc(struct filedesc_to_leader *old, struct filedesc *fdp, struct proc *leader)
int sys_getdtablesize(struct thread *td, struct getdtablesize_args *uap)
int fget_unlocked(struct thread *td, int fd, cap_rights_t *needrightsp, struct file **fpp)
struct fileops badfileops
void pwd_set_rootvnode(void)
static void fdused(struct filedesc *fdp, int fd)
int fdlastfile_single(struct filedesc *fdp)
int kern_fstat(struct thread *td, int fd, struct stat *sbp)
int fgetvp_rights(struct thread *td, int fd, cap_rights_t *needrightsp, struct filecaps *havecaps, struct vnode **vpp)
int dupfdopen(struct thread *td, struct filedesc *fdp, int dfd, int mode, int openerror, int *indxp)
void finit(struct file *fp, u_int flag, short type, void *data, struct fileops *ops)
static bool is_unsafe(struct file *fp)
static MALLOC_DEFINE(M_FILEDESC, "filedesc", "Open file descriptor table")
static struct filedesc * fdhold(struct proc *p)
int kern_fcntl_freebsd(struct thread *td, int fd, int cmd, long arg)
int fget_read(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp)
static int sysctl_kern_proc_cwd(SYSCTL_HANDLER_ARGS)
int fdalloc(struct thread *td, int minfd, int *result)
struct pwddesc * pdcopy(struct pwddesc *pdp)
int invfo_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio, struct uio *trl_uio, off_t offset, size_t nbytes, off_t *sent, int flags, struct thread *td)
static __read_mostly uma_zone_t file_zone
static int sysctl_kern_file(SYSCTL_HANDLER_ARGS)
static int fget_unlocked_seq(struct thread *td, int fd, cap_rights_t *needrightsp, struct file **fpp, seqc_t *seqp)
int kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
SYSINIT(select, SI_SUB_LOCK, SI_ORDER_FIRST, filelistinit, NULL)
struct fileops path_fileops
static struct cdevsw fildesc_cdevsw
void finit_vnode(struct file *fp, u_int flag, void *data, struct fileops *ops)
void fdescfree(struct thread *td)
int sys_dup2(struct thread *td, struct dup2_args *uap)
int kern_proc_cwd_out(struct proc *p, struct sbuf *sb, ssize_t maxlen)
static void export_vnode_to_kinfo(struct vnode *vp, int fd, int fflags, struct kinfo_file *kif, int flags)
int invfo_rdwr(struct file *fp, struct uio *uio, struct ucred *active_cred, int flags, struct thread *td)
__read_mostly uma_zone_t pwd_zone
static void pddrop(struct pwddesc *pdp)
static int closefp_hl(struct filedesc *fdp, int fd, struct file *fp, struct thread *td, bool holdleaders, bool audit)
static __read_mostly uma_zone_t filedesc0_zone
int invfo_kqfilter(struct file *fp, struct knote *kn)
static int close_range_impl(struct thread *td, u_int lowfd, u_int highfd)
static int path_close(struct file *fp, struct thread *td)
#define FILEDESC_FOREACH_FDE(fdp, _iterator, _fde)
int fget_fcntl(struct thread *td, int fd, cap_rights_t *rightsp, int needfcntl, struct file **fpp)
static void filelistinit(void *dummy)
static int export_file_to_sb(struct file *fp, int fd, cap_rights_t *rightsp, struct export_fd_buf *efbuf)
int falloc_caps(struct thread *td, struct file **resultfp, int *resultfd, int flags, struct filecaps *fcaps)
int invfo_chmod(struct file *fp, mode_t mode, struct ucred *active_cred, struct thread *td)
int kern_close_range(struct thread *td, int flags, u_int lowfd, u_int highfd)
static int getmaxfd(struct thread *td)
static int badfo_truncate(struct file *fp, off_t length, struct ucred *active_cred, struct thread *td)
SLIST_HEAD(et_eventtimers_list, eventtimer)
void knote_fdclose(struct thread *td, int fd)
void knote(struct knlist *list, long hint, int lockflags)
struct prisonlist allprison
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
void free(void *addr, struct malloc_type *mtp)
static struct pollrec pr[POLL_LIST_LEN]
int priv_check(struct thread *td, int priv)
struct sx __exclusive_cache_line proctree_lock
int pget(pid_t pid, int flags, struct proc **pp)
struct sx __exclusive_cache_line allproc_lock
struct pgrp * pgfind(pid_t pgid)
int p_cansee(struct thread *td, struct proc *p)
struct ucred * crhold(struct ucred *cr)
void crfree(struct ucred *cr)
rlim_t() lim_cur(struct thread *td, int which)
void panic(const char *fmt,...)
void wakeup(const void *ident)
int sysctl_wire_old_buffer(struct sysctl_req *req, size_t len)
struct sbuf * sbuf_new_for_sysctl(struct sbuf *s, char *buf, int length, struct sysctl_req *req)
int ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps)
struct intr_irqsrc ** src
struct filedescent fdt_ofiles[NDFILE]
struct fdescenttbl * ft_table
static bool kasan_enabled __read_mostly
__read_mostly cap_rights_t cap_no_rights
__read_mostly cap_rights_t cap_flock_rights
__read_mostly cap_rights_t cap_fcntl_rights
bool cap_rights_is_valid(const cap_rights_t *rights)
__read_mostly cap_rights_t cap_fpathconf_rights
__read_mostly cap_rights_t cap_fstat_rights
int printf(const char *fmt,...)
void sbuf_clear_flags(struct sbuf *s, int flags)
int sbuf_finish(struct sbuf *s)
void sbuf_delete(struct sbuf *s)
int sbuf_bcat(struct sbuf *s, const void *buf, size_t len)
int sbuf_error(const struct sbuf *s)
int poll_no_poll(int events)
void vref(struct vnode *vp)
void vrefact(struct vnode *vp)
void vrele(struct vnode *vp)
void vdrop(struct vnode *vp)
int kern_openat(struct thread *td, int fd, const char *path, enum uio_seg pathseg, int flags, int mode)
int vn_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
int vn_statfile(struct file *fp, struct stat *sb, struct ucred *active_cred)
int vn_fill_kinfo_vnode(struct vnode *vp, struct kinfo_file *kif)
int vn_kqfilter_opath(struct file *fp, struct knote *kn)