Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_descrip.c
| Show First 20 Lines • Show All 3,084 Lines • ▼ Show 20 Lines | pack_kinfo(struct kinfo_file *kif) | ||||
| kif->kf_structsize = offsetof(struct kinfo_file, kf_path) + | kif->kf_structsize = offsetof(struct kinfo_file, kf_path) + | ||||
| strlen(kif->kf_path) + 1; | strlen(kif->kf_path) + 1; | ||||
| kif->kf_structsize = roundup(kif->kf_structsize, sizeof(uint64_t)); | kif->kf_structsize = roundup(kif->kf_structsize, sizeof(uint64_t)); | ||||
| } | } | ||||
| static void | static void | ||||
| export_file_to_kinfo(struct file *fp, int fd, cap_rights_t *rightsp, | export_file_to_kinfo(struct file *fp, int fd, cap_rights_t *rightsp, | ||||
| struct kinfo_file *kif, struct filedesc *fdp) | struct kinfo_file *kif, struct filedesc *fdp, int lkflags) | ||||
| { | { | ||||
| int error; | int error; | ||||
| bzero(kif, sizeof(*kif)); | bzero(kif, sizeof(*kif)); | ||||
| /* Set a default type to allow for empty fill_kinfo() methods. */ | /* Set a default type to allow for empty fill_kinfo() methods. */ | ||||
| kif->kf_type = KF_TYPE_UNKNOWN; | kif->kf_type = KF_TYPE_UNKNOWN; | ||||
| kif->kf_flags = xlate_fflags(fp->f_flag); | kif->kf_flags = xlate_fflags(fp->f_flag); | ||||
| if (rightsp != NULL) | if (rightsp != NULL) | ||||
| kif->kf_cap_rights = *rightsp; | kif->kf_cap_rights = *rightsp; | ||||
| else | else | ||||
| cap_rights_init(&kif->kf_cap_rights); | cap_rights_init(&kif->kf_cap_rights); | ||||
| kif->kf_fd = fd; | kif->kf_fd = fd; | ||||
| kif->kf_ref_count = fp->f_count; | kif->kf_ref_count = fp->f_count; | ||||
| kif->kf_offset = foffset_get(fp); | kif->kf_offset = foffset_get(fp); | ||||
| /* | /* | ||||
| * This may drop the filedesc lock, so the 'fp' cannot be | * This may drop the filedesc lock, so the 'fp' cannot be | ||||
| * accessed after this call. | * accessed after this call. | ||||
| */ | */ | ||||
| error = fo_fill_kinfo(fp, kif, fdp); | error = fo_fill_kinfo(fp, kif, fdp, lkflags); | ||||
| if (error == 0) | if (error == 0) | ||||
| kif->kf_status |= KF_ATTR_VALID; | kif->kf_status |= KF_ATTR_VALID; | ||||
| pack_kinfo(kif); | pack_kinfo(kif); | ||||
| } | } | ||||
| static void | static void | ||||
| export_vnode_to_kinfo(struct vnode *vp, int fd, int fflags, | export_vnode_to_kinfo(struct vnode *vp, int fd, int fflags, | ||||
| struct kinfo_file *kif) | struct kinfo_file *kif, int lkflags) | ||||
| { | { | ||||
| int error; | int error; | ||||
| bzero(kif, sizeof(*kif)); | bzero(kif, sizeof(*kif)); | ||||
| kif->kf_type = KF_TYPE_VNODE; | kif->kf_type = KF_TYPE_VNODE; | ||||
| error = vn_fill_kinfo_vnode(vp, kif); | error = vn_fill_kinfo_vnode(vp, kif, lkflags); | ||||
| if (error == 0) | if (error == 0) | ||||
| kif->kf_status |= KF_ATTR_VALID; | kif->kf_status |= KF_ATTR_VALID; | ||||
| kif->kf_flags = xlate_fflags(fflags); | kif->kf_flags = xlate_fflags(fflags); | ||||
| cap_rights_init(&kif->kf_cap_rights); | cap_rights_init(&kif->kf_cap_rights); | ||||
| kif->kf_fd = fd; | kif->kf_fd = fd; | ||||
| kif->kf_ref_count = -1; | kif->kf_ref_count = -1; | ||||
| kif->kf_offset = -1; | kif->kf_offset = -1; | ||||
| pack_kinfo(kif); | pack_kinfo(kif); | ||||
| Show All 21 Lines | if (efbuf->remainder != -1) { | ||||
| } | } | ||||
| efbuf->remainder -= kif->kf_structsize; | efbuf->remainder -= kif->kf_structsize; | ||||
| } | } | ||||
| return (sbuf_bcat(efbuf->sb, kif, kif->kf_structsize) == 0 ? 0 : ENOMEM); | return (sbuf_bcat(efbuf->sb, kif, kif->kf_structsize) == 0 ? 0 : ENOMEM); | ||||
| } | } | ||||
| static int | static int | ||||
| export_file_to_sb(struct file *fp, int fd, cap_rights_t *rightsp, | export_file_to_sb(struct file *fp, int fd, cap_rights_t *rightsp, | ||||
| struct export_fd_buf *efbuf) | struct export_fd_buf *efbuf, int lkflags) | ||||
| { | { | ||||
| int error; | int error; | ||||
| if (efbuf->remainder == 0) | if (efbuf->remainder == 0) | ||||
| return (0); | return (0); | ||||
| export_file_to_kinfo(fp, fd, rightsp, &efbuf->kif, efbuf->fdp); | export_file_to_kinfo(fp, fd, rightsp, &efbuf->kif, efbuf->fdp, lkflags); | ||||
| FILEDESC_SUNLOCK(efbuf->fdp); | FILEDESC_SUNLOCK(efbuf->fdp); | ||||
| error = export_kinfo_to_sb(efbuf); | error = export_kinfo_to_sb(efbuf); | ||||
| FILEDESC_SLOCK(efbuf->fdp); | FILEDESC_SLOCK(efbuf->fdp); | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| static int | static int | ||||
| export_vnode_to_sb(struct vnode *vp, int fd, int fflags, | export_vnode_to_sb(struct vnode *vp, int fd, int fflags, | ||||
| struct export_fd_buf *efbuf) | struct export_fd_buf *efbuf, int lkflags) | ||||
| { | { | ||||
| int error; | int error; | ||||
| if (efbuf->remainder == 0) | if (efbuf->remainder == 0) | ||||
| return (0); | return (0); | ||||
| if (efbuf->fdp != NULL) | if (efbuf->fdp != NULL) | ||||
| FILEDESC_SUNLOCK(efbuf->fdp); | FILEDESC_SUNLOCK(efbuf->fdp); | ||||
| export_vnode_to_kinfo(vp, fd, fflags, &efbuf->kif); | export_vnode_to_kinfo(vp, fd, fflags, &efbuf->kif, lkflags); | ||||
| error = export_kinfo_to_sb(efbuf); | error = export_kinfo_to_sb(efbuf); | ||||
| if (efbuf->fdp != NULL) | if (efbuf->fdp != NULL) | ||||
| FILEDESC_SLOCK(efbuf->fdp); | FILEDESC_SLOCK(efbuf->fdp); | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| /* | /* | ||||
| * Store a process file descriptor information to sbuf. | * Store a process file descriptor information to sbuf. | ||||
| * | * | ||||
| * Takes a locked proc as argument, and returns with the proc unlocked. | * Takes a locked proc as argument, and returns with the proc unlocked. | ||||
| * | |||||
| * LK_NOWAIT may be passed in lkflags to avoid sleeping on vnode locks. | |||||
| */ | */ | ||||
| int | int | ||||
| kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen) | kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen, | ||||
| int lkflags) | |||||
| { | { | ||||
| struct file *fp; | struct file *fp; | ||||
| struct filedesc *fdp; | struct filedesc *fdp; | ||||
| struct export_fd_buf *efbuf; | struct export_fd_buf *efbuf; | ||||
| struct vnode *cttyvp, *textvp, *tracevp; | struct vnode *cttyvp, *textvp, *tracevp; | ||||
| int error, i; | int error, i; | ||||
| cap_rights_t rights; | cap_rights_t rights; | ||||
| Show All 17 Lines | kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen, | ||||
| fdp = fdhold(p); | fdp = fdhold(p); | ||||
| PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
| efbuf = malloc(sizeof(*efbuf), M_TEMP, M_WAITOK); | efbuf = malloc(sizeof(*efbuf), M_TEMP, M_WAITOK); | ||||
| efbuf->fdp = NULL; | efbuf->fdp = NULL; | ||||
| efbuf->sb = sb; | efbuf->sb = sb; | ||||
| efbuf->remainder = maxlen; | efbuf->remainder = maxlen; | ||||
| if (tracevp != NULL) | if (tracevp != NULL) | ||||
| export_vnode_to_sb(tracevp, KF_FD_TYPE_TRACE, FREAD | FWRITE, | export_vnode_to_sb(tracevp, KF_FD_TYPE_TRACE, FREAD | FWRITE, | ||||
| efbuf); | efbuf, lkflags); | ||||
| if (textvp != NULL) | if (textvp != NULL) | ||||
| export_vnode_to_sb(textvp, KF_FD_TYPE_TEXT, FREAD, efbuf); | export_vnode_to_sb(textvp, KF_FD_TYPE_TEXT, FREAD, efbuf, | ||||
| lkflags); | |||||
| if (cttyvp != NULL) | if (cttyvp != NULL) | ||||
| export_vnode_to_sb(cttyvp, KF_FD_TYPE_CTTY, FREAD | FWRITE, | export_vnode_to_sb(cttyvp, KF_FD_TYPE_CTTY, FREAD | FWRITE, | ||||
| efbuf); | efbuf, lkflags); | ||||
| error = 0; | error = 0; | ||||
| if (fdp == NULL) | if (fdp == NULL) | ||||
| goto fail; | goto fail; | ||||
| efbuf->fdp = fdp; | efbuf->fdp = fdp; | ||||
| FILEDESC_SLOCK(fdp); | FILEDESC_SLOCK(fdp); | ||||
| /* working directory */ | /* working directory */ | ||||
| if (fdp->fd_cdir != NULL) { | if (fdp->fd_cdir != NULL) { | ||||
| vref(fdp->fd_cdir); | vref(fdp->fd_cdir); | ||||
| export_vnode_to_sb(fdp->fd_cdir, KF_FD_TYPE_CWD, FREAD, efbuf); | export_vnode_to_sb(fdp->fd_cdir, KF_FD_TYPE_CWD, FREAD, efbuf, | ||||
| lkflags); | |||||
| } | } | ||||
| /* root directory */ | /* root directory */ | ||||
| if (fdp->fd_rdir != NULL) { | if (fdp->fd_rdir != NULL) { | ||||
| vref(fdp->fd_rdir); | vref(fdp->fd_rdir); | ||||
| export_vnode_to_sb(fdp->fd_rdir, KF_FD_TYPE_ROOT, FREAD, efbuf); | export_vnode_to_sb(fdp->fd_rdir, KF_FD_TYPE_ROOT, FREAD, efbuf, | ||||
| lkflags); | |||||
| } | } | ||||
| /* jail directory */ | /* jail directory */ | ||||
| if (fdp->fd_jdir != NULL) { | if (fdp->fd_jdir != NULL) { | ||||
| vref(fdp->fd_jdir); | vref(fdp->fd_jdir); | ||||
| export_vnode_to_sb(fdp->fd_jdir, KF_FD_TYPE_JAIL, FREAD, efbuf); | export_vnode_to_sb(fdp->fd_jdir, KF_FD_TYPE_JAIL, FREAD, efbuf, | ||||
| lkflags); | |||||
| } | } | ||||
| for (i = 0; fdp->fd_refcnt > 0 && i <= fdp->fd_lastfile; i++) { | for (i = 0; fdp->fd_refcnt > 0 && i <= fdp->fd_lastfile; i++) { | ||||
| if ((fp = fdp->fd_ofiles[i].fde_file) == NULL) | if ((fp = fdp->fd_ofiles[i].fde_file) == NULL) | ||||
| continue; | continue; | ||||
| #ifdef CAPABILITIES | #ifdef CAPABILITIES | ||||
| rights = *cap_rights(fdp, i); | rights = *cap_rights(fdp, i); | ||||
| #else /* !CAPABILITIES */ | #else /* !CAPABILITIES */ | ||||
| cap_rights_init(&rights); | cap_rights_init(&rights); | ||||
| #endif | #endif | ||||
| /* | /* | ||||
| * Create sysctl entry. It is OK to drop the filedesc | * Create sysctl entry. It is OK to drop the filedesc | ||||
| * lock inside of export_file_to_sb() as we will | * lock inside of export_file_to_sb() as we will | ||||
| * re-validate and re-evaluate its properties when the | * re-validate and re-evaluate its properties when the | ||||
| * loop continues. | * loop continues. | ||||
| */ | */ | ||||
| error = export_file_to_sb(fp, i, &rights, efbuf); | error = export_file_to_sb(fp, i, &rights, efbuf, lkflags); | ||||
| if (error != 0 || efbuf->remainder == 0) | if (error != 0 || efbuf->remainder == 0) | ||||
| break; | break; | ||||
| } | } | ||||
| FILEDESC_SUNLOCK(fdp); | FILEDESC_SUNLOCK(fdp); | ||||
| fddrop(fdp); | fddrop(fdp); | ||||
| fail: | fail: | ||||
| free(efbuf, M_TEMP); | free(efbuf, M_TEMP); | ||||
| return (error); | return (error); | ||||
| Show All 17 Lines | sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS) | ||||
| sbuf_new_for_sysctl(&sb, NULL, FILEDESC_SBUF_SIZE, req); | sbuf_new_for_sysctl(&sb, NULL, FILEDESC_SBUF_SIZE, req); | ||||
| sbuf_clear_flags(&sb, SBUF_INCLUDENUL); | sbuf_clear_flags(&sb, SBUF_INCLUDENUL); | ||||
| error = pget((pid_t)name[0], PGET_CANDEBUG | PGET_NOTWEXIT, &p); | error = pget((pid_t)name[0], PGET_CANDEBUG | PGET_NOTWEXIT, &p); | ||||
| if (error != 0) { | if (error != 0) { | ||||
| sbuf_delete(&sb); | sbuf_delete(&sb); | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| maxlen = req->oldptr != NULL ? req->oldlen : -1; | maxlen = req->oldptr != NULL ? req->oldlen : -1; | ||||
| error = kern_proc_filedesc_out(p, &sb, maxlen); | error = kern_proc_filedesc_out(p, &sb, maxlen, 0); | ||||
| error2 = sbuf_finish(&sb); | error2 = sbuf_finish(&sb); | ||||
| sbuf_delete(&sb); | sbuf_delete(&sb); | ||||
| return (error != 0 ? error : error2); | return (error != 0 ? error : error2); | ||||
| } | } | ||||
| #ifdef KINFO_OFILE_SIZE | #ifdef KINFO_OFILE_SIZE | ||||
| CTASSERT(sizeof(struct kinfo_ofile) == KINFO_OFILE_SIZE); | CTASSERT(sizeof(struct kinfo_ofile) == KINFO_OFILE_SIZE); | ||||
| #endif | #endif | ||||
| Show All 23 Lines | |||||
| static int | static int | ||||
| export_vnode_for_osysctl(struct vnode *vp, int type, struct kinfo_file *kif, | export_vnode_for_osysctl(struct vnode *vp, int type, struct kinfo_file *kif, | ||||
| struct kinfo_ofile *okif, struct filedesc *fdp, struct sysctl_req *req) | struct kinfo_ofile *okif, struct filedesc *fdp, struct sysctl_req *req) | ||||
| { | { | ||||
| int error; | int error; | ||||
| vref(vp); | vref(vp); | ||||
| FILEDESC_SUNLOCK(fdp); | FILEDESC_SUNLOCK(fdp); | ||||
| export_vnode_to_kinfo(vp, type, 0, kif); | export_vnode_to_kinfo(vp, type, 0, kif, 0); | ||||
| kinfo_to_okinfo(kif, okif); | kinfo_to_okinfo(kif, okif); | ||||
| error = SYSCTL_OUT(req, okif, sizeof(*okif)); | error = SYSCTL_OUT(req, okif, sizeof(*okif)); | ||||
| FILEDESC_SLOCK(fdp); | FILEDESC_SLOCK(fdp); | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| /* | /* | ||||
| * Get per-process file descriptors for use by procstat(1), et al. | * Get per-process file descriptors for use by procstat(1), et al. | ||||
| Show All 26 Lines | if (fdp->fd_rdir != NULL) | ||||
| export_vnode_for_osysctl(fdp->fd_rdir, KF_FD_TYPE_ROOT, kif, | export_vnode_for_osysctl(fdp->fd_rdir, KF_FD_TYPE_ROOT, kif, | ||||
| okif, fdp, req); | okif, fdp, req); | ||||
| if (fdp->fd_jdir != NULL) | if (fdp->fd_jdir != NULL) | ||||
| export_vnode_for_osysctl(fdp->fd_jdir, KF_FD_TYPE_JAIL, kif, | export_vnode_for_osysctl(fdp->fd_jdir, KF_FD_TYPE_JAIL, kif, | ||||
| okif, fdp, req); | okif, fdp, req); | ||||
| for (i = 0; fdp->fd_refcnt > 0 && i <= fdp->fd_lastfile; i++) { | for (i = 0; fdp->fd_refcnt > 0 && i <= fdp->fd_lastfile; i++) { | ||||
| if ((fp = fdp->fd_ofiles[i].fde_file) == NULL) | if ((fp = fdp->fd_ofiles[i].fde_file) == NULL) | ||||
| continue; | continue; | ||||
| export_file_to_kinfo(fp, i, NULL, kif, fdp); | export_file_to_kinfo(fp, i, NULL, kif, fdp, 0); | ||||
| FILEDESC_SUNLOCK(fdp); | FILEDESC_SUNLOCK(fdp); | ||||
| kinfo_to_okinfo(kif, okif); | kinfo_to_okinfo(kif, okif); | ||||
| error = SYSCTL_OUT(req, okif, sizeof(*okif)); | error = SYSCTL_OUT(req, okif, sizeof(*okif)); | ||||
| FILEDESC_SLOCK(fdp); | FILEDESC_SLOCK(fdp); | ||||
| if (error) | if (error) | ||||
| break; | break; | ||||
| } | } | ||||
| FILEDESC_SUNLOCK(fdp); | FILEDESC_SUNLOCK(fdp); | ||||
| ▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | kern_proc_cwd_out(struct proc *p, struct sbuf *sb, ssize_t maxlen) | ||||
| efbuf->remainder = maxlen; | efbuf->remainder = maxlen; | ||||
| FILEDESC_SLOCK(fdp); | FILEDESC_SLOCK(fdp); | ||||
| if (fdp->fd_cdir == NULL) | if (fdp->fd_cdir == NULL) | ||||
| error = EINVAL; | error = EINVAL; | ||||
| else { | else { | ||||
| vref(fdp->fd_cdir); | vref(fdp->fd_cdir); | ||||
| error = export_vnode_to_sb(fdp->fd_cdir, KF_FD_TYPE_CWD, | error = export_vnode_to_sb(fdp->fd_cdir, KF_FD_TYPE_CWD, | ||||
| FREAD, efbuf); | FREAD, efbuf, 0); | ||||
| } | } | ||||
| FILEDESC_SUNLOCK(fdp); | FILEDESC_SUNLOCK(fdp); | ||||
| fddrop(fdp); | fddrop(fdp); | ||||
| free(efbuf, M_TEMP); | free(efbuf, M_TEMP); | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| /* | /* | ||||
| ▲ Show 20 Lines • Show All 239 Lines • ▼ Show 20 Lines | 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 uio *trl_uio, off_t offset, size_t nbytes, off_t *sent, int flags, | ||||
| int kflags, struct thread *td) | int kflags, struct thread *td) | ||||
| { | { | ||||
| return (EBADF); | return (EBADF); | ||||
| } | } | ||||
| static int | static int | ||||
| badfo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp) | badfo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp, | ||||
| int lkflags) | |||||
| { | { | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| struct fileops badfileops = { | struct fileops badfileops = { | ||||
| .fo_read = badfo_readwrite, | .fo_read = badfo_readwrite, | ||||
| .fo_write = badfo_readwrite, | .fo_write = badfo_readwrite, | ||||
| ▲ Show 20 Lines • Show All 129 Lines • Show Last 20 Lines | |||||