static void fstat_kvm(int what, int arg) { struct kinfo_proc *p, *plast; char buf[_POSIX2_LINE_MAX]; int cnt; ALLOC_OFILES(256); /* reserve space for file pointers */ /* * Discard setgid privileges if not the running kernel so that bad * guys can't print interesting stuff from kernel memory. */ if (nlistf != NULL || memf != NULL) setgid(getgid()); if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == NULL) errx(1, "%s", buf); setgid(getgid()); #ifdef notdef if (kvm_nlist(kd, nl) != 0) errx(1, "no namelist: %s", kvm_geterr(kd)); #endif if ((p = kvm_getprocs(kd, what, arg, &cnt)) == NULL) errx(1, "%s", kvm_geterr(kd)); print_header(); for (plast = &p[cnt]; p < plast; ++p) { if (p->ki_stat == SZOMB) continue; dofiles(p); if (mflg) dommap(p); } }
/* * print open files attributed to this process */ void dofiles(struct kinfo_proc *kp, struct proc *p) { int i; struct file file; struct filedesc filed; struct ktrace_node ktrace_node; Uname = user_from_uid(kp->kp_uid, 0); Pid = kp->kp_pid; Comm = kp->kp_comm; make_printable(Comm, strlen(Comm)); if (p->p_fd == NULL) return; if (!kread(p->p_fd, &filed, sizeof (filed))) { dprintf(stderr, "can't read filedesc at %p for pid %d\n", (void *)p->p_fd, Pid); return; } /* * root directory vnode, if one */ if (filed.fd_rdir) vtrans(filed.fd_rdir, &filed.fd_nrdir, RDIR, FREAD, 0); /* * current working directory vnode */ vtrans(filed.fd_cdir, &filed.fd_ncdir, CDIR, FREAD, 0); /* * ktrace vnode, if one */ if (p->p_tracenode) { if (kread(p->p_tracenode, &ktrace_node, sizeof (ktrace_node))) vtrans(ktrace_node.kn_vp, NULL, TRACE, FREAD|FWRITE, 0); } /* * text vnode, if one */ if (p->p_textvp) vtrans(p->p_textvp, NULL, TEXT, FREAD, 0); /* * open files */ ALLOC_OFILES(filed.fd_lastfile+1); if (!kread(filed.fd_files, ofiles, (filed.fd_lastfile+1) * sizeof(struct fdnode))) { dprintf(stderr, "can't read file structures at %p for pid %d\n", (void *)filed.fd_files, Pid); return; } for (i = 0; i <= filed.fd_lastfile; i++) { if (ofiles[i].fp == NULL) continue; if (!kread(ofiles[i].fp, &file, sizeof (struct file))) { dprintf(stderr, "can't read file %d at %p for pid %d\n", i, (void *)ofiles[i].fp, Pid); continue; } if (file.f_type == DTYPE_VNODE) { vtrans((struct vnode *)file.f_data, &file.f_nchandle, i, file.f_flag, file.f_offset); } else if (file.f_type == DTYPE_SOCKET) { if (checkfile == 0) socktrans((struct socket *)file.f_data, i); } #ifdef DTYPE_PIPE else if (file.f_type == DTYPE_PIPE) { if (checkfile == 0) pipetrans((struct pipe *)file.f_data, i, file.f_flag); } #endif #ifdef DTYPE_FIFO else if (file.f_type == DTYPE_FIFO) { if (checkfile == 0) vtrans((struct vnode *)file.f_data, &file.f_nchandle, i, file.f_flag, file.f_offset); } #endif else { dprintf(stderr, "unknown file type %d for file %d of pid %d\n", file.f_type, i, Pid); } } }
int main(int argc, char **argv) { struct passwd *passwd; struct kinfo_proc *p, *plast; struct proc proc; int arg, ch, what; char *memf, *nlistf; char buf[_POSIX2_LINE_MAX]; int cnt; arg = 0; what = KERN_PROC_ALL; nlistf = memf = NULL; while ((ch = getopt(argc, argv, "fmnp:u:vwN:M:")) != -1) switch((char)ch) { case 'f': fsflg = 1; break; case 'M': memf = optarg; break; case 'N': nlistf = optarg; break; case 'm': mflg = 1; break; case 'n': nflg = 1; break; case 'p': if (pflg++) usage(); if (!isdigit(*optarg)) { warnx("-p requires a process id"); usage(); } what = KERN_PROC_PID; arg = atoi(optarg); break; case 'u': if (uflg++) usage(); if (!(passwd = getpwnam(optarg))) errx(1, "%s: unknown uid", optarg); what = KERN_PROC_UID; arg = passwd->pw_uid; break; case 'v': vflg = 1; break; case 'w': wflg_mnt = 40; wflg_cmd = 16; break; case '?': default: usage(); } if (*(argv += optind)) { for (; *argv; ++argv) { if (getfname(*argv)) checkfile = 1; } if (!checkfile) /* file(s) specified, but none accessable */ exit(1); } ALLOC_OFILES(256); /* reserve space for file pointers */ if (fsflg && !checkfile) { /* -f with no files means use wd */ if (getfname(".") == 0) exit(1); checkfile = 1; } /* * Discard setgid privileges if not the running kernel so that bad * guys can't print interesting stuff from kernel memory. */ if (nlistf != NULL || memf != NULL) setgid(getgid()); if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == NULL) errx(1, "%s", buf); #ifdef notdef if (kvm_nlist(kd, nl) != 0) errx(1, "no namelist: %s", kvm_geterr(kd)); #endif if ((p = kvm_getprocs(kd, what, arg, &cnt)) == NULL) errx(1, "%s", kvm_geterr(kd)); if (nflg) printf("USER %-*.*s %*.*s FD DEV %*.*s MODE SZ|DV R/W", wflg_cmd, wflg_cmd, "CMD", pid_width, pid_width, "PID", ino_width, ino_width, "INUM"); else printf("USER %-*.*s %*.*s FD %-*.*s %*.*s MODE SZ|DV R/W", wflg_cmd, wflg_cmd, "CMD", pid_width, pid_width, "PID", wflg_mnt, wflg_mnt, "PATH", ino_width, ino_width, "INUM"); if (checkfile && fsflg == 0) printf(" NAME\n"); else putchar('\n'); for (plast = &p[cnt]; p < plast; ++p) { if (p->kp_stat == SZOMB) continue; if (!kread((void *)p->kp_paddr, &proc, sizeof(proc))) { dprintf(stderr, "can't read proc at %p for pid %d\n", (void *)p->kp_paddr, Pid); continue; } dofiles(p, &proc); if (mflg) dommap(&proc); } exit(0); }
/* * print open files attributed to this process */ void dofiles(struct kinfo_proc2 *kp) { int i; struct file file; struct filedesc0 filed0; #define filed filed0.fd_fd Uname = user_from_uid(kp->p_uid, 0); Pid = kp->p_pid; Comm = kp->p_comm; if (kp->p_fd == 0) return; if (!KVM_READ(kp->p_fd, &filed0, sizeof (filed0))) { dprintf("can't read filedesc at %p for pid %ld", (void *)(u_long)kp->p_fd, (long)Pid); return; } if (filed.fd_nfiles < 0 || filed.fd_lastfile >= filed.fd_nfiles || filed.fd_freefile > filed.fd_lastfile + 1) { dprintf("filedesc corrupted at %p for pid %ld", (void *)(u_long)kp->p_fd, (long)Pid); return; } /* * root directory vnode, if one */ if (filed.fd_rdir) vtrans(filed.fd_rdir, RDIR, FREAD, 0); /* * current working directory vnode */ vtrans(filed.fd_cdir, CDIR, FREAD, 0); /* * ktrace vnode, if one */ if (kp->p_tracep) vtrans((struct vnode *)(u_long)kp->p_tracep, TRACE, FREAD|FWRITE, 0); /* * open files */ #define FPSIZE (sizeof (struct file *)) ALLOC_OFILES(filed.fd_lastfile+1); if (filed.fd_nfiles > NDFILE) { if (!KVM_READ(filed.fd_ofiles, ofiles, (filed.fd_lastfile+1) * FPSIZE)) { dprintf("can't read file structures at %p for pid %ld", filed.fd_ofiles, (long)Pid); return; } } else bcopy(filed0.fd_dfiles, ofiles, (filed.fd_lastfile+1) * FPSIZE); for (i = 0; i <= filed.fd_lastfile; i++) { if (ofiles[i] == NULL) continue; if (!KVM_READ(ofiles[i], &file, sizeof (struct file))) { dprintf("can't read file %d at %p for pid %ld", i, ofiles[i], (long)Pid); continue; } if (file.f_type == DTYPE_VNODE) vtrans((struct vnode *)file.f_data, i, file.f_flag, file.f_offset); else if (file.f_type == DTYPE_SOCKET) { if (checkfile == 0) socktrans((struct socket *)file.f_data, i); } else if (file.f_type == DTYPE_PIPE) { if (checkfile == 0) pipetrans((struct pipe *)file.f_data, i); } else if (file.f_type == DTYPE_KQUEUE) { if (checkfile == 0) kqueuetrans((struct kqueue *)file.f_data, i); } else if (file.f_type == DTYPE_CRYPTO) { if (checkfile == 0) cryptotrans(file.f_data, i); } else if (file.f_type == DTYPE_SYSTRACE) { if (checkfile == 0) systracetrans((struct fsystrace *)file.f_data, i); } else { dprintf("unknown file type %d for file %d of pid %ld", file.f_type, i, (long)Pid); } } }
int main(int argc, char *argv[]) { extern char *optarg; extern int optind; struct passwd *passwd; struct kinfo_proc2 *p, *plast; int arg, ch, what; char *memf, *nlistf; char buf[_POSIX2_LINE_MAX]; int cnt; arg = 0; what = KERN_PROC_ALL; nlistf = memf = NULL; oflg = 0; while ((ch = getopt(argc, argv, "fnop:u:vN:M:")) != -1) switch((char)ch) { case 'f': fsflg = 1; break; case 'M': memf = optarg; break; case 'N': nlistf = optarg; break; case 'n': nflg = 1; break; case 'o': oflg = 1; break; case 'p': if (pflg++) usage(); if (!isdigit(*optarg)) { warnx( "-p requires a process id"); usage(); } what = KERN_PROC_PID; arg = atoi(optarg); break; case 'u': if (uflg++) usage(); if (!(passwd = getpwnam(optarg))) errx(1, "%s: unknown uid", optarg); what = KERN_PROC_UID; arg = passwd->pw_uid; break; case 'v': vflg = 1; break; default: usage(); } /* * Discard setgid privileges if not the running kernel so that bad * guys can't print interesting stuff from kernel memory. */ if (nlistf != NULL || memf != NULL) { setegid(getgid()); setgid(getgid()); } if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == NULL) errx(1, "%s", buf); setegid(getgid()); setgid(getgid()); if (*(argv += optind)) { for (; *argv; ++argv) { if (getfname(*argv)) checkfile = 1; } if (!checkfile) /* file(s) specified, but none accessible */ exit(1); } ALLOC_OFILES(256); /* reserve space for file pointers */ if (fsflg && !checkfile) { /* -f with no files means use wd */ if (getfname(".") == 0) exit(1); checkfile = 1; } if ((p = kvm_getproc2(kd, what, arg, sizeof(*p), &cnt)) == NULL) errx(1, "%s", kvm_geterr(kd)); if (nflg) printf("%s", "USER CMD PID FD DEV INUM MODE R/W DV|SZ"); else printf("%s", "USER CMD PID FD MOUNT INUM MODE R/W DV|SZ"); if (oflg) printf("%s", ":OFFSET "); if (checkfile && fsflg == 0) printf(" NAME\n"); else putchar('\n'); for (plast = &p[cnt]; p < plast; ++p) { if (p->p_stat == SZOMB) continue; dofiles(p); } exit(0); }
/* * print open files attributed to this process */ void dofiles(struct kinfo_proc *kp) { int i; struct file file; struct filedesc filed; Uname = user_from_uid(kp->ki_uid, 0); Pid = kp->ki_pid; Comm = kp->ki_comm; if (kp->ki_fd == NULL) return; if (!KVM_READ(kp->ki_fd, &filed, sizeof (filed))) { dprintf(stderr, "can't read filedesc at %p for pid %d\n", (void *)kp->ki_fd, Pid); return; } /* * root directory vnode, if one */ if (filed.fd_rdir) vtrans(filed.fd_rdir, RDIR, FREAD); /* * current working directory vnode */ if (filed.fd_cdir) vtrans(filed.fd_cdir, CDIR, FREAD); /* * jail root, if any. */ if (filed.fd_jdir) vtrans(filed.fd_jdir, JDIR, FREAD); /* * ktrace vnode, if one */ if (kp->ki_tracep) vtrans(kp->ki_tracep, TRACE, FREAD|FWRITE); /* * text vnode, if one */ if (kp->ki_textvp) vtrans(kp->ki_textvp, TEXT, FREAD); /* * open files */ #define FPSIZE (sizeof (struct file *)) #define MAX_LASTFILE (0x1000000) /* Sanity check on filed.fd_lastfile */ if (filed.fd_lastfile <= -1 || filed.fd_lastfile > MAX_LASTFILE) return; ALLOC_OFILES(filed.fd_lastfile+1); if (!KVM_READ(filed.fd_ofiles, ofiles, (filed.fd_lastfile+1) * FPSIZE)) { dprintf(stderr, "can't read file structures at %p for pid %d\n", (void *)filed.fd_ofiles, Pid); return; } for (i = 0; i <= filed.fd_lastfile; i++) { if (ofiles[i] == NULL) continue; if (!KVM_READ(ofiles[i], &file, sizeof (struct file))) { dprintf(stderr, "can't read file %d at %p for pid %d\n", i, (void *)ofiles[i], Pid); continue; } if (file.f_type == DTYPE_VNODE) vtrans(file.f_vnode, i, file.f_flag); else if (file.f_type == DTYPE_SOCKET) { if (checkfile == 0) socktrans(file.f_data, i); } #ifdef DTYPE_PIPE else if (file.f_type == DTYPE_PIPE) { if (checkfile == 0) pipetrans(file.f_data, i, file.f_flag); } #endif #ifdef DTYPE_FIFO else if (file.f_type == DTYPE_FIFO) { if (checkfile == 0) vtrans(file.f_vnode, i, file.f_flag); } #endif #ifdef DTYPE_PTS else if (file.f_type == DTYPE_PTS) { if (checkfile == 0) ptstrans(file.f_data, i, file.f_flag); } #endif else { dprintf(stderr, "unknown file type %d for file %d of pid %d\n", file.f_type, i, Pid); } } }