diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 4914804b5e5f..7e5306259493 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -2446,6 +2446,47 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS) SYSCTL_PROC(_kern, KERN_FILE, file, CTLTYPE_OPAQUE|CTLFLAG_RD, 0, 0, sysctl_kern_file, "S,xfile", "Entire file table"); +static int +export_vnode_for_sysctl(struct vnode *vp, int type, + struct kinfo_file *kif, struct filedesc *fdp, struct sysctl_req *req) +{ + int error; + char *fullpath, *freepath; + int vfslocked; + + bzero(kif, sizeof(*kif)); + kif->kf_structsize = sizeof(*kif); + + vref(vp); + kif->kf_fd = type; + kif->kf_type = KF_TYPE_VNODE; + /* This function only handles directories. */ + KASSERT(vp->v_type == VDIR, ("export_vnode_for_sysctl: vnode not directory")); + kif->kf_vnode_type = KF_VTYPE_VDIR; + + /* + * This is not a true file descriptor, so we set a bogus refcount + * and offset to indicate these fields should be ignored. + */ + kif->kf_ref_count = -1; + kif->kf_offset = -1; + + freepath = NULL; + fullpath = "-"; + FILEDESC_SUNLOCK(fdp); + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + vn_fullpath(curthread, vp, &fullpath, &freepath); + vput(vp); + VFS_UNLOCK_GIANT(vfslocked); + strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path)); + if (freepath != NULL) + free(freepath, M_TEMP); + error = SYSCTL_OUT(req, kif, sizeof(*kif)); + FILEDESC_SLOCK(fdp); + return (error); +} + /* * Get per-process file descriptors for use by procstat(1), et al. */ @@ -2473,6 +2514,15 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS) PROC_UNLOCK(p); kif = malloc(sizeof(*kif), M_TEMP, M_WAITOK); FILEDESC_SLOCK(fdp); + if (fdp->fd_cdir != NULL) + export_vnode_for_sysctl(fdp->fd_cdir, KF_FD_TYPE_CWD, kif, + fdp, req); + if (fdp->fd_rdir != NULL) + export_vnode_for_sysctl(fdp->fd_rdir, KF_FD_TYPE_ROOT, kif, + fdp, req); + if (fdp->fd_jdir != NULL) + export_vnode_for_sysctl(fdp->fd_jdir, KF_FD_TYPE_JAIL, kif, + fdp, req); for (i = 0; i < fdp->fd_nfiles; i++) { if ((fp = fdp->fd_ofiles[i]) == NULL) continue; diff --git a/sys/sys/param.h b/sys/sys/param.h index a7ff20a5389d..1a21dc2d0317 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -57,7 +57,7 @@ * is created, otherwise 1. */ #undef __FreeBSD_version -#define __FreeBSD_version 800018 /* Master, propagated to newvers */ +#define __FreeBSD_version 800019 /* Master, propagated to newvers */ #ifndef LOCORE #include diff --git a/sys/sys/user.h b/sys/sys/user.h index 8177b1b2972f..55954760494d 100644 --- a/sys/sys/user.h +++ b/sys/sys/user.h @@ -234,7 +234,7 @@ struct user { }; /* - * The KERN_PROC_FILE sysctl allows a process to dumpt the file descriptor + * The KERN_PROC_FILE sysctl allows a process to dump the file descriptor * array of another process. */ #define KF_TYPE_NONE 0 @@ -259,6 +259,10 @@ struct user { #define KF_VTYPE_VBAD 8 #define KF_VTYPE_UNKNOWN 255 +#define KF_FD_TYPE_CWD -1 /* Current working directory */ +#define KF_FD_TYPE_ROOT -2 /* Root directory */ +#define KF_FD_TYPE_JAIL -3 /* Jail directory */ + #define KF_FLAG_READ 0x00000001 #define KF_FLAG_WRITE 0x00000002 #define KF_FLAG_APPEND 0x00000004 diff --git a/usr.bin/procstat/procstat_files.c b/usr.bin/procstat/procstat_files.c index 98e4ef6767c3..950b70df2761 100644 --- a/usr.bin/procstat/procstat_files.c +++ b/usr.bin/procstat/procstat_files.c @@ -140,7 +140,7 @@ procstat_files(pid_t pid, struct kinfo_proc *kipp) size_t len; if (!hflag) - printf("%5s %-16s %3s %1s %1s %-8s %3s %7s %-3s %-12s\n", + printf("%5s %-16s %4s %1s %1s %-8s %3s %7s %-3s %-12s\n", "PID", "COMM", "FD", "T", "V", "FLAGS", "REF", "OFFSET", "PRO", "NAME"); @@ -172,7 +172,23 @@ procstat_files(pid_t pid, struct kinfo_proc *kipp) errx(-1, "kinfo_file mismatch"); printf("%5d ", pid); printf("%-16s ", kipp->ki_comm); - printf("%3d ", kif->kf_fd); + switch (kif->kf_fd) { + case KF_FD_TYPE_CWD: + printf(" cwd "); + break; + + case KF_FD_TYPE_ROOT: + printf("root "); + break; + + case KF_FD_TYPE_JAIL: + printf("jail "); + break; + + default: + printf("%4d ", kif->kf_fd); + break; + } switch (kif->kf_type) { case KF_TYPE_VNODE: str = "v"; @@ -264,8 +280,14 @@ procstat_files(pid_t pid, struct kinfo_proc *kipp) printf("%s", kif->kf_flags & KF_FLAG_NONBLOCK ? "n" : "-"); printf("%s", kif->kf_flags & KF_FLAG_DIRECT ? "d" : "-"); printf("%s ", kif->kf_flags & KF_FLAG_HASLOCK ? "l" : "-"); - printf("%3d ", kif->kf_ref_count); - printf("%7jd ", (intmax_t)kif->kf_offset); + if (kif->kf_ref_count > -1) + printf("%3d ", kif->kf_ref_count); + else + printf("%3c ", '-'); + if (kif->kf_offset > -1) + printf("%7jd ", (intmax_t)kif->kf_offset); + else + printf("%7c ", '-'); switch (kif->kf_type) { case KF_TYPE_VNODE: