libprocstat.c 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766
  1. /*-
  2. * SPDX-License-Identifier: BSD-4-Clause
  3. *
  4. * Copyright (c) 2017 Dell EMC
  5. * Copyright (c) 2009 Stanislav Sedov <stas@FreeBSD.org>
  6. * Copyright (c) 1988, 1993
  7. * The Regents of the University of California. All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. All advertising materials mentioning features or use of this software
  18. * must display the following acknowledgement:
  19. * This product includes software developed by the University of
  20. * California, Berkeley and its contributors.
  21. * 4. Neither the name of the University nor the names of its contributors
  22. * may be used to endorse or promote products derived from this software
  23. * without specific prior written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35. * SUCH DAMAGE.
  36. */
  37. #include <sys/param.h>
  38. #include <sys/elf.h>
  39. #include <sys/time.h>
  40. #include <sys/resourcevar.h>
  41. #define _WANT_UCRED
  42. #include <sys/ucred.h>
  43. #undef _WANT_UCRED
  44. #include <sys/proc.h>
  45. #include <sys/user.h>
  46. #include <sys/stat.h>
  47. #include <sys/vnode.h>
  48. #include <sys/socket.h>
  49. #define _WANT_SOCKET
  50. #include <sys/socketvar.h>
  51. #include <sys/domain.h>
  52. #include <sys/protosw.h>
  53. #include <sys/un.h>
  54. #define _WANT_UNPCB
  55. #include <sys/unpcb.h>
  56. #include <sys/sysctl.h>
  57. #include <sys/tty.h>
  58. #include <sys/filedesc.h>
  59. #include <sys/queue.h>
  60. #define _WANT_FILE
  61. #include <sys/file.h>
  62. #include <sys/conf.h>
  63. #include <sys/ksem.h>
  64. #include <sys/mman.h>
  65. #include <sys/capsicum.h>
  66. #include <sys/ptrace.h>
  67. #define _WANT_MOUNT
  68. #include <sys/mount.h>
  69. #include <sys/filedesc.h>
  70. #include <sys/pipe.h>
  71. #include <fs/devfs/devfs.h>
  72. #include <fs/devfs/devfs_int.h>
  73. #include <nfs/nfsproto.h>
  74. #include <nfsclient/nfs.h>
  75. #include <nfsclient/nfsnode.h>
  76. #include <vm/vm.h>
  77. #include <vm/vm_map.h>
  78. #include <vm/vm_object.h>
  79. #include <net/route.h>
  80. #include <netinet/in.h>
  81. #include <netinet/in_systm.h>
  82. #include <netinet/ip.h>
  83. #include <assert.h>
  84. #include <ctype.h>
  85. #include <err.h>
  86. #include <fcntl.h>
  87. #include <kvm.h>
  88. #include <libutil.h>
  89. #include <limits.h>
  90. #include <paths.h>
  91. #include <pwd.h>
  92. #include <stdio.h>
  93. #include <stdlib.h>
  94. #include <stddef.h>
  95. #include <string.h>
  96. #include <unistd.h>
  97. #include <netdb.h>
  98. #include <libprocstat.h>
  99. #include "libprocstat_internal.h"
  100. #include "common_kvm.h"
  101. #include "core.h"
  102. int statfs(const char *, struct statfs *); /* XXX */
  103. #define PROCSTAT_KVM 1
  104. #define PROCSTAT_SYSCTL 2
  105. #define PROCSTAT_CORE 3
  106. static char **getargv(struct procstat *procstat, struct kinfo_proc *kp,
  107. size_t nchr, int env);
  108. static char *getmnton(kvm_t *kd, struct mount *m);
  109. static struct kinfo_vmentry * kinfo_getvmmap_core(struct procstat_core *core,
  110. int *cntp);
  111. static Elf_Auxinfo *procstat_getauxv_core(struct procstat_core *core,
  112. unsigned int *cntp);
  113. static Elf_Auxinfo *procstat_getauxv_sysctl(pid_t pid, unsigned int *cntp);
  114. static struct filestat_list *procstat_getfiles_kvm(
  115. struct procstat *procstat, struct kinfo_proc *kp, int mmapped);
  116. static struct filestat_list *procstat_getfiles_sysctl(
  117. struct procstat *procstat, struct kinfo_proc *kp, int mmapped);
  118. static int procstat_get_pipe_info_sysctl(struct filestat *fst,
  119. struct pipestat *pipe, char *errbuf);
  120. static int procstat_get_pipe_info_kvm(kvm_t *kd, struct filestat *fst,
  121. struct pipestat *pipe, char *errbuf);
  122. static int procstat_get_pts_info_sysctl(struct filestat *fst,
  123. struct ptsstat *pts, char *errbuf);
  124. static int procstat_get_pts_info_kvm(kvm_t *kd, struct filestat *fst,
  125. struct ptsstat *pts, char *errbuf);
  126. static int procstat_get_sem_info_sysctl(struct filestat *fst,
  127. struct semstat *sem, char *errbuf);
  128. static int procstat_get_sem_info_kvm(kvm_t *kd, struct filestat *fst,
  129. struct semstat *sem, char *errbuf);
  130. static int procstat_get_shm_info_sysctl(struct filestat *fst,
  131. struct shmstat *shm, char *errbuf);
  132. static int procstat_get_shm_info_kvm(kvm_t *kd, struct filestat *fst,
  133. struct shmstat *shm, char *errbuf);
  134. static int procstat_get_socket_info_sysctl(struct filestat *fst,
  135. struct sockstat *sock, char *errbuf);
  136. static int procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst,
  137. struct sockstat *sock, char *errbuf);
  138. static int to_filestat_flags(int flags);
  139. static int procstat_get_vnode_info_kvm(kvm_t *kd, struct filestat *fst,
  140. struct vnstat *vn, char *errbuf);
  141. static int procstat_get_vnode_info_sysctl(struct filestat *fst,
  142. struct vnstat *vn, char *errbuf);
  143. static gid_t *procstat_getgroups_core(struct procstat_core *core,
  144. unsigned int *count);
  145. static gid_t * procstat_getgroups_kvm(kvm_t *kd, struct kinfo_proc *kp,
  146. unsigned int *count);
  147. static gid_t *procstat_getgroups_sysctl(pid_t pid, unsigned int *count);
  148. static struct kinfo_kstack *procstat_getkstack_sysctl(pid_t pid,
  149. int *cntp);
  150. static int procstat_getosrel_core(struct procstat_core *core,
  151. int *osrelp);
  152. static int procstat_getosrel_kvm(kvm_t *kd, struct kinfo_proc *kp,
  153. int *osrelp);
  154. static int procstat_getosrel_sysctl(pid_t pid, int *osrelp);
  155. static int procstat_getpathname_core(struct procstat_core *core,
  156. char *pathname, size_t maxlen);
  157. static int procstat_getpathname_sysctl(pid_t pid, char *pathname,
  158. size_t maxlen);
  159. static int procstat_getrlimit_core(struct procstat_core *core, int which,
  160. struct rlimit* rlimit);
  161. static int procstat_getrlimit_kvm(kvm_t *kd, struct kinfo_proc *kp,
  162. int which, struct rlimit* rlimit);
  163. static int procstat_getrlimit_sysctl(pid_t pid, int which,
  164. struct rlimit* rlimit);
  165. static int procstat_getumask_core(struct procstat_core *core,
  166. unsigned short *maskp);
  167. static int procstat_getumask_kvm(kvm_t *kd, struct kinfo_proc *kp,
  168. unsigned short *maskp);
  169. static int procstat_getumask_sysctl(pid_t pid, unsigned short *maskp);
  170. static int vntype2psfsttype(int type);
  171. void
  172. procstat_close(struct procstat *procstat)
  173. {
  174. assert(procstat);
  175. if (procstat->type == PROCSTAT_KVM)
  176. kvm_close(procstat->kd);
  177. else if (procstat->type == PROCSTAT_CORE)
  178. procstat_core_close(procstat->core);
  179. procstat_freeargv(procstat);
  180. procstat_freeenvv(procstat);
  181. free(procstat);
  182. }
  183. struct procstat *
  184. procstat_open_sysctl(void)
  185. {
  186. struct procstat *procstat;
  187. procstat = calloc(1, sizeof(*procstat));
  188. if (procstat == NULL) {
  189. warn("malloc()");
  190. return (NULL);
  191. }
  192. procstat->type = PROCSTAT_SYSCTL;
  193. return (procstat);
  194. }
  195. struct procstat *
  196. procstat_open_kvm(const char *nlistf, const char *memf)
  197. {
  198. struct procstat *procstat;
  199. kvm_t *kd;
  200. char buf[_POSIX2_LINE_MAX];
  201. procstat = calloc(1, sizeof(*procstat));
  202. if (procstat == NULL) {
  203. warn("malloc()");
  204. return (NULL);
  205. }
  206. kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf);
  207. if (kd == NULL) {
  208. warnx("kvm_openfiles(): %s", buf);
  209. free(procstat);
  210. return (NULL);
  211. }
  212. procstat->type = PROCSTAT_KVM;
  213. procstat->kd = kd;
  214. return (procstat);
  215. }
  216. struct procstat *
  217. procstat_open_core(const char *filename)
  218. {
  219. struct procstat *procstat;
  220. struct procstat_core *core;
  221. procstat = calloc(1, sizeof(*procstat));
  222. if (procstat == NULL) {
  223. warn("malloc()");
  224. return (NULL);
  225. }
  226. core = procstat_core_open(filename);
  227. if (core == NULL) {
  228. free(procstat);
  229. return (NULL);
  230. }
  231. procstat->type = PROCSTAT_CORE;
  232. procstat->core = core;
  233. return (procstat);
  234. }
  235. struct kinfo_proc *
  236. procstat_getprocs(struct procstat *procstat, int what, int arg,
  237. unsigned int *count)
  238. {
  239. struct kinfo_proc *p0, *p;
  240. size_t len, olen;
  241. int name[4];
  242. int cnt;
  243. int error;
  244. assert(procstat);
  245. assert(count);
  246. p = NULL;
  247. if (procstat->type == PROCSTAT_KVM) {
  248. *count = 0;
  249. p0 = kvm_getprocs(procstat->kd, what, arg, &cnt);
  250. if (p0 == NULL || cnt <= 0)
  251. return (NULL);
  252. *count = cnt;
  253. len = *count * sizeof(*p);
  254. p = malloc(len);
  255. if (p == NULL) {
  256. warnx("malloc(%zu)", len);
  257. goto fail;
  258. }
  259. bcopy(p0, p, len);
  260. return (p);
  261. } else if (procstat->type == PROCSTAT_SYSCTL) {
  262. len = 0;
  263. name[0] = CTL_KERN;
  264. name[1] = KERN_PROC;
  265. name[2] = what;
  266. name[3] = arg;
  267. error = sysctl(name, nitems(name), NULL, &len, NULL, 0);
  268. if (error < 0 && errno != EPERM) {
  269. warn("sysctl(kern.proc)");
  270. goto fail;
  271. }
  272. if (len == 0) {
  273. warnx("no processes?");
  274. goto fail;
  275. }
  276. do {
  277. len += len / 10;
  278. p = reallocf(p, len);
  279. if (p == NULL) {
  280. warnx("reallocf(%zu)", len);
  281. goto fail;
  282. }
  283. olen = len;
  284. error = sysctl(name, nitems(name), p, &len, NULL, 0);
  285. } while (error < 0 && errno == ENOMEM && olen == len);
  286. if (error < 0 && errno != EPERM) {
  287. warn("sysctl(kern.proc)");
  288. goto fail;
  289. }
  290. /* Perform simple consistency checks. */
  291. if ((len % sizeof(*p)) != 0 || p->ki_structsize != sizeof(*p)) {
  292. warnx("kinfo_proc structure size mismatch (len = %zu)", len);
  293. goto fail;
  294. }
  295. *count = len / sizeof(*p);
  296. return (p);
  297. } else if (procstat->type == PROCSTAT_CORE) {
  298. p = procstat_core_get(procstat->core, PSC_TYPE_PROC, NULL,
  299. &len);
  300. if ((len % sizeof(*p)) != 0 || p->ki_structsize != sizeof(*p)) {
  301. warnx("kinfo_proc structure size mismatch");
  302. goto fail;
  303. }
  304. *count = len / sizeof(*p);
  305. return (p);
  306. } else {
  307. warnx("unknown access method: %d", procstat->type);
  308. return (NULL);
  309. }
  310. fail:
  311. if (p)
  312. free(p);
  313. return (NULL);
  314. }
  315. void
  316. procstat_freeprocs(struct procstat *procstat __unused, struct kinfo_proc *p)
  317. {
  318. if (p != NULL)
  319. free(p);
  320. p = NULL;
  321. }
  322. struct filestat_list *
  323. procstat_getfiles(struct procstat *procstat, struct kinfo_proc *kp, int mmapped)
  324. {
  325. switch (procstat->type) {
  326. case PROCSTAT_KVM:
  327. return (procstat_getfiles_kvm(procstat, kp, mmapped));
  328. case PROCSTAT_SYSCTL:
  329. case PROCSTAT_CORE:
  330. return (procstat_getfiles_sysctl(procstat, kp, mmapped));
  331. default:
  332. warnx("unknown access method: %d", procstat->type);
  333. return (NULL);
  334. }
  335. }
  336. void
  337. procstat_freefiles(struct procstat *procstat, struct filestat_list *head)
  338. {
  339. struct filestat *fst, *tmp;
  340. STAILQ_FOREACH_SAFE(fst, head, next, tmp) {
  341. if (fst->fs_path != NULL)
  342. free(fst->fs_path);
  343. free(fst);
  344. }
  345. free(head);
  346. if (procstat->vmentries != NULL) {
  347. free(procstat->vmentries);
  348. procstat->vmentries = NULL;
  349. }
  350. if (procstat->files != NULL) {
  351. free(procstat->files);
  352. procstat->files = NULL;
  353. }
  354. }
  355. static struct filestat *
  356. filestat_new_entry(void *typedep, int type, int fd, int fflags, int uflags,
  357. int refcount, off_t offset, char *path, cap_rights_t *cap_rightsp)
  358. {
  359. struct filestat *entry;
  360. entry = calloc(1, sizeof(*entry));
  361. if (entry == NULL) {
  362. warn("malloc()");
  363. return (NULL);
  364. }
  365. entry->fs_typedep = typedep;
  366. entry->fs_fflags = fflags;
  367. entry->fs_uflags = uflags;
  368. entry->fs_fd = fd;
  369. entry->fs_type = type;
  370. entry->fs_ref_count = refcount;
  371. entry->fs_offset = offset;
  372. entry->fs_path = path;
  373. if (cap_rightsp != NULL)
  374. entry->fs_cap_rights = *cap_rightsp;
  375. else
  376. cap_rights_init(&entry->fs_cap_rights);
  377. return (entry);
  378. }
  379. static struct vnode *
  380. getctty(kvm_t *kd, struct kinfo_proc *kp)
  381. {
  382. struct pgrp pgrp;
  383. struct proc proc;
  384. struct session sess;
  385. int error;
  386. assert(kp);
  387. error = kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc,
  388. sizeof(proc));
  389. if (error == 0) {
  390. warnx("can't read proc struct at %p for pid %d",
  391. kp->ki_paddr, kp->ki_pid);
  392. return (NULL);
  393. }
  394. if (proc.p_pgrp == NULL)
  395. return (NULL);
  396. error = kvm_read_all(kd, (unsigned long)proc.p_pgrp, &pgrp,
  397. sizeof(pgrp));
  398. if (error == 0) {
  399. warnx("can't read pgrp struct at %p for pid %d",
  400. proc.p_pgrp, kp->ki_pid);
  401. return (NULL);
  402. }
  403. error = kvm_read_all(kd, (unsigned long)pgrp.pg_session, &sess,
  404. sizeof(sess));
  405. if (error == 0) {
  406. warnx("can't read session struct at %p for pid %d",
  407. pgrp.pg_session, kp->ki_pid);
  408. return (NULL);
  409. }
  410. return (sess.s_ttyvp);
  411. }
  412. static int
  413. procstat_vm_map_reader(void *token, vm_map_entry_t addr, vm_map_entry_t dest)
  414. {
  415. kvm_t *kd;
  416. kd = (kvm_t *)token;
  417. return (kvm_read_all(kd, (unsigned long)addr, dest, sizeof(*dest)));
  418. }
  419. static struct filestat_list *
  420. procstat_getfiles_kvm(struct procstat *procstat, struct kinfo_proc *kp, int mmapped)
  421. {
  422. struct file file;
  423. struct filedesc filed;
  424. struct pwddesc pathsd;
  425. struct fdescenttbl *fdt;
  426. struct pwd pwd;
  427. unsigned long pwd_addr;
  428. struct vm_map_entry vmentry;
  429. struct vm_object object;
  430. struct vmspace vmspace;
  431. vm_map_entry_t entryp;
  432. vm_object_t objp;
  433. struct vnode *vp;
  434. struct filestat *entry;
  435. struct filestat_list *head;
  436. kvm_t *kd;
  437. void *data;
  438. int fflags;
  439. unsigned int i;
  440. int prot, type;
  441. size_t fdt_size;
  442. unsigned int nfiles;
  443. bool haspwd;
  444. assert(procstat);
  445. kd = procstat->kd;
  446. if (kd == NULL)
  447. return (NULL);
  448. if (kp->ki_fd == NULL || kp->ki_pd == NULL)
  449. return (NULL);
  450. if (!kvm_read_all(kd, (unsigned long)kp->ki_fd, &filed,
  451. sizeof(filed))) {
  452. warnx("can't read filedesc at %p", (void *)kp->ki_fd);
  453. return (NULL);
  454. }
  455. if (!kvm_read_all(kd, (unsigned long)kp->ki_pd, &pathsd,
  456. sizeof(pathsd))) {
  457. warnx("can't read pwddesc at %p", (void *)kp->ki_pd);
  458. return (NULL);
  459. }
  460. haspwd = false;
  461. pwd_addr = (unsigned long)(PWDDESC_KVM_LOAD_PWD(&pathsd));
  462. if (pwd_addr != 0) {
  463. if (!kvm_read_all(kd, pwd_addr, &pwd, sizeof(pwd))) {
  464. warnx("can't read fd_pwd at %p", (void *)pwd_addr);
  465. return (NULL);
  466. }
  467. haspwd = true;
  468. }
  469. /*
  470. * Allocate list head.
  471. */
  472. head = malloc(sizeof(*head));
  473. if (head == NULL)
  474. return (NULL);
  475. STAILQ_INIT(head);
  476. /* root directory vnode, if one. */
  477. if (haspwd) {
  478. if (pwd.pwd_rdir) {
  479. entry = filestat_new_entry(pwd.pwd_rdir, PS_FST_TYPE_VNODE, -1,
  480. PS_FST_FFLAG_READ, PS_FST_UFLAG_RDIR, 0, 0, NULL, NULL);
  481. if (entry != NULL)
  482. STAILQ_INSERT_TAIL(head, entry, next);
  483. }
  484. /* current working directory vnode. */
  485. if (pwd.pwd_cdir) {
  486. entry = filestat_new_entry(pwd.pwd_cdir, PS_FST_TYPE_VNODE, -1,
  487. PS_FST_FFLAG_READ, PS_FST_UFLAG_CDIR, 0, 0, NULL, NULL);
  488. if (entry != NULL)
  489. STAILQ_INSERT_TAIL(head, entry, next);
  490. }
  491. /* jail root, if any. */
  492. if (pwd.pwd_jdir) {
  493. entry = filestat_new_entry(pwd.pwd_jdir, PS_FST_TYPE_VNODE, -1,
  494. PS_FST_FFLAG_READ, PS_FST_UFLAG_JAIL, 0, 0, NULL, NULL);
  495. if (entry != NULL)
  496. STAILQ_INSERT_TAIL(head, entry, next);
  497. }
  498. }
  499. /* ktrace vnode, if one */
  500. if (kp->ki_tracep) {
  501. entry = filestat_new_entry(kp->ki_tracep, PS_FST_TYPE_VNODE, -1,
  502. PS_FST_FFLAG_READ | PS_FST_FFLAG_WRITE,
  503. PS_FST_UFLAG_TRACE, 0, 0, NULL, NULL);
  504. if (entry != NULL)
  505. STAILQ_INSERT_TAIL(head, entry, next);
  506. }
  507. /* text vnode, if one */
  508. if (kp->ki_textvp) {
  509. entry = filestat_new_entry(kp->ki_textvp, PS_FST_TYPE_VNODE, -1,
  510. PS_FST_FFLAG_READ, PS_FST_UFLAG_TEXT, 0, 0, NULL, NULL);
  511. if (entry != NULL)
  512. STAILQ_INSERT_TAIL(head, entry, next);
  513. }
  514. /* Controlling terminal. */
  515. if ((vp = getctty(kd, kp)) != NULL) {
  516. entry = filestat_new_entry(vp, PS_FST_TYPE_VNODE, -1,
  517. PS_FST_FFLAG_READ | PS_FST_FFLAG_WRITE,
  518. PS_FST_UFLAG_CTTY, 0, 0, NULL, NULL);
  519. if (entry != NULL)
  520. STAILQ_INSERT_TAIL(head, entry, next);
  521. }
  522. if (!kvm_read_all(kd, (unsigned long)filed.fd_files, &nfiles,
  523. sizeof(nfiles))) {
  524. warnx("can't read fd_files at %p", (void *)filed.fd_files);
  525. return (NULL);
  526. }
  527. fdt_size = sizeof(*fdt) + nfiles * sizeof(struct filedescent);
  528. fdt = malloc(fdt_size);
  529. if (fdt == NULL) {
  530. warn("malloc(%zu)", fdt_size);
  531. goto do_mmapped;
  532. }
  533. if (!kvm_read_all(kd, (unsigned long)filed.fd_files, fdt, fdt_size)) {
  534. warnx("cannot read file structures at %p", (void *)filed.fd_files);
  535. free(fdt);
  536. goto do_mmapped;
  537. }
  538. for (i = 0; i < nfiles; i++) {
  539. if (fdt->fdt_ofiles[i].fde_file == NULL) {
  540. continue;
  541. }
  542. if (!kvm_read_all(kd, (unsigned long)fdt->fdt_ofiles[i].fde_file, &file,
  543. sizeof(struct file))) {
  544. warnx("can't read file %d at %p", i,
  545. (void *)fdt->fdt_ofiles[i].fde_file);
  546. continue;
  547. }
  548. switch (file.f_type) {
  549. case DTYPE_VNODE:
  550. type = PS_FST_TYPE_VNODE;
  551. data = file.f_vnode;
  552. break;
  553. case DTYPE_SOCKET:
  554. type = PS_FST_TYPE_SOCKET;
  555. data = file.f_data;
  556. break;
  557. case DTYPE_PIPE:
  558. type = PS_FST_TYPE_PIPE;
  559. data = file.f_data;
  560. break;
  561. case DTYPE_FIFO:
  562. type = PS_FST_TYPE_FIFO;
  563. data = file.f_vnode;
  564. break;
  565. #ifdef DTYPE_PTS
  566. case DTYPE_PTS:
  567. type = PS_FST_TYPE_PTS;
  568. data = file.f_data;
  569. break;
  570. #endif
  571. case DTYPE_SEM:
  572. type = PS_FST_TYPE_SEM;
  573. data = file.f_data;
  574. break;
  575. case DTYPE_SHM:
  576. type = PS_FST_TYPE_SHM;
  577. data = file.f_data;
  578. break;
  579. case DTYPE_PROCDESC:
  580. type = PS_FST_TYPE_PROCDESC;
  581. data = file.f_data;
  582. break;
  583. case DTYPE_DEV:
  584. type = PS_FST_TYPE_DEV;
  585. data = file.f_data;
  586. break;
  587. case DTYPE_EVENTFD:
  588. type = PS_FST_TYPE_EVENTFD;
  589. data = file.f_data;
  590. break;
  591. default:
  592. continue;
  593. }
  594. /* XXXRW: No capability rights support for kvm yet. */
  595. entry = filestat_new_entry(data, type, i,
  596. to_filestat_flags(file.f_flag), 0, 0, 0, NULL, NULL);
  597. if (entry != NULL)
  598. STAILQ_INSERT_TAIL(head, entry, next);
  599. }
  600. free(fdt);
  601. do_mmapped:
  602. /*
  603. * Process mmapped files if requested.
  604. */
  605. if (mmapped) {
  606. if (!kvm_read_all(kd, (unsigned long)kp->ki_vmspace, &vmspace,
  607. sizeof(vmspace))) {
  608. warnx("can't read vmspace at %p",
  609. (void *)kp->ki_vmspace);
  610. goto exit;
  611. }
  612. vmentry = vmspace.vm_map.header;
  613. for (entryp = vm_map_entry_read_succ(kd, &vmentry, procstat_vm_map_reader);
  614. entryp != NULL && entryp != &kp->ki_vmspace->vm_map.header;
  615. entryp = vm_map_entry_read_succ(kd, &vmentry, procstat_vm_map_reader)) {
  616. if (vmentry.eflags & MAP_ENTRY_IS_SUB_MAP)
  617. continue;
  618. if ((objp = vmentry.object.vm_object) == NULL)
  619. continue;
  620. for (; objp; objp = object.backing_object) {
  621. if (!kvm_read_all(kd, (unsigned long)objp,
  622. &object, sizeof(object))) {
  623. warnx("can't read vm_object at %p",
  624. (void *)objp);
  625. break;
  626. }
  627. }
  628. /* We want only vnode objects. */
  629. if (object.type != OBJT_VNODE)
  630. continue;
  631. prot = vmentry.protection;
  632. fflags = 0;
  633. if (prot & VM_PROT_READ)
  634. fflags = PS_FST_FFLAG_READ;
  635. if ((vmentry.eflags & MAP_ENTRY_COW) == 0 &&
  636. prot & VM_PROT_WRITE)
  637. fflags |= PS_FST_FFLAG_WRITE;
  638. /*
  639. * Create filestat entry.
  640. */
  641. entry = filestat_new_entry(object.handle,
  642. PS_FST_TYPE_VNODE, -1, fflags,
  643. PS_FST_UFLAG_MMAP, 0, 0, NULL, NULL);
  644. if (entry != NULL)
  645. STAILQ_INSERT_TAIL(head, entry, next);
  646. }
  647. if (entryp == NULL)
  648. warnx("can't read vm_map_entry");
  649. }
  650. exit:
  651. return (head);
  652. }
  653. /*
  654. * kinfo types to filestat translation.
  655. */
  656. static int
  657. kinfo_type2fst(int kftype)
  658. {
  659. static struct {
  660. int kf_type;
  661. int fst_type;
  662. } kftypes2fst[] = {
  663. { KF_TYPE_PROCDESC, PS_FST_TYPE_PROCDESC },
  664. { KF_TYPE_DEV, PS_FST_TYPE_DEV },
  665. { KF_TYPE_FIFO, PS_FST_TYPE_FIFO },
  666. { KF_TYPE_KQUEUE, PS_FST_TYPE_KQUEUE },
  667. { KF_TYPE_MQUEUE, PS_FST_TYPE_MQUEUE },
  668. { KF_TYPE_NONE, PS_FST_TYPE_NONE },
  669. { KF_TYPE_PIPE, PS_FST_TYPE_PIPE },
  670. { KF_TYPE_PTS, PS_FST_TYPE_PTS },
  671. { KF_TYPE_SEM, PS_FST_TYPE_SEM },
  672. { KF_TYPE_SHM, PS_FST_TYPE_SHM },
  673. { KF_TYPE_SOCKET, PS_FST_TYPE_SOCKET },
  674. { KF_TYPE_VNODE, PS_FST_TYPE_VNODE },
  675. { KF_TYPE_EVENTFD, PS_FST_TYPE_EVENTFD },
  676. { KF_TYPE_UNKNOWN, PS_FST_TYPE_UNKNOWN }
  677. };
  678. #define NKFTYPES (sizeof(kftypes2fst) / sizeof(*kftypes2fst))
  679. unsigned int i;
  680. for (i = 0; i < NKFTYPES; i++)
  681. if (kftypes2fst[i].kf_type == kftype)
  682. break;
  683. if (i == NKFTYPES)
  684. return (PS_FST_TYPE_UNKNOWN);
  685. return (kftypes2fst[i].fst_type);
  686. }
  687. /*
  688. * kinfo flags to filestat translation.
  689. */
  690. static int
  691. kinfo_fflags2fst(int kfflags)
  692. {
  693. static struct {
  694. int kf_flag;
  695. int fst_flag;
  696. } kfflags2fst[] = {
  697. { KF_FLAG_APPEND, PS_FST_FFLAG_APPEND },
  698. { KF_FLAG_ASYNC, PS_FST_FFLAG_ASYNC },
  699. { KF_FLAG_CREAT, PS_FST_FFLAG_CREAT },
  700. { KF_FLAG_DIRECT, PS_FST_FFLAG_DIRECT },
  701. { KF_FLAG_EXCL, PS_FST_FFLAG_EXCL },
  702. { KF_FLAG_EXEC, PS_FST_FFLAG_EXEC },
  703. { KF_FLAG_EXLOCK, PS_FST_FFLAG_EXLOCK },
  704. { KF_FLAG_FSYNC, PS_FST_FFLAG_SYNC },
  705. { KF_FLAG_HASLOCK, PS_FST_FFLAG_HASLOCK },
  706. { KF_FLAG_NOFOLLOW, PS_FST_FFLAG_NOFOLLOW },
  707. { KF_FLAG_NONBLOCK, PS_FST_FFLAG_NONBLOCK },
  708. { KF_FLAG_READ, PS_FST_FFLAG_READ },
  709. { KF_FLAG_SHLOCK, PS_FST_FFLAG_SHLOCK },
  710. { KF_FLAG_TRUNC, PS_FST_FFLAG_TRUNC },
  711. { KF_FLAG_WRITE, PS_FST_FFLAG_WRITE }
  712. };
  713. #define NKFFLAGS (sizeof(kfflags2fst) / sizeof(*kfflags2fst))
  714. unsigned int i;
  715. int flags;
  716. flags = 0;
  717. for (i = 0; i < NKFFLAGS; i++)
  718. if ((kfflags & kfflags2fst[i].kf_flag) != 0)
  719. flags |= kfflags2fst[i].fst_flag;
  720. return (flags);
  721. }
  722. static int
  723. kinfo_uflags2fst(int fd)
  724. {
  725. switch (fd) {
  726. case KF_FD_TYPE_CTTY:
  727. return (PS_FST_UFLAG_CTTY);
  728. case KF_FD_TYPE_CWD:
  729. return (PS_FST_UFLAG_CDIR);
  730. case KF_FD_TYPE_JAIL:
  731. return (PS_FST_UFLAG_JAIL);
  732. case KF_FD_TYPE_TEXT:
  733. return (PS_FST_UFLAG_TEXT);
  734. case KF_FD_TYPE_TRACE:
  735. return (PS_FST_UFLAG_TRACE);
  736. case KF_FD_TYPE_ROOT:
  737. return (PS_FST_UFLAG_RDIR);
  738. }
  739. return (0);
  740. }
  741. static struct kinfo_file *
  742. kinfo_getfile_core(struct procstat_core *core, int *cntp)
  743. {
  744. int cnt;
  745. size_t len;
  746. char *buf, *bp, *eb;
  747. struct kinfo_file *kif, *kp, *kf;
  748. buf = procstat_core_get(core, PSC_TYPE_FILES, NULL, &len);
  749. if (buf == NULL)
  750. return (NULL);
  751. /*
  752. * XXXMG: The code below is just copy&past from libutil.
  753. * The code duplication can be avoided if libutil
  754. * is extended to provide something like:
  755. * struct kinfo_file *kinfo_getfile_from_buf(const char *buf,
  756. * size_t len, int *cntp);
  757. */
  758. /* Pass 1: count items */
  759. cnt = 0;
  760. bp = buf;
  761. eb = buf + len;
  762. while (bp < eb) {
  763. kf = (struct kinfo_file *)(uintptr_t)bp;
  764. if (kf->kf_structsize == 0)
  765. break;
  766. bp += kf->kf_structsize;
  767. cnt++;
  768. }
  769. kif = calloc(cnt, sizeof(*kif));
  770. if (kif == NULL) {
  771. free(buf);
  772. return (NULL);
  773. }
  774. bp = buf;
  775. eb = buf + len;
  776. kp = kif;
  777. /* Pass 2: unpack */
  778. while (bp < eb) {
  779. kf = (struct kinfo_file *)(uintptr_t)bp;
  780. if (kf->kf_structsize == 0)
  781. break;
  782. /* Copy/expand into pre-zeroed buffer */
  783. memcpy(kp, kf, kf->kf_structsize);
  784. /* Advance to next packed record */
  785. bp += kf->kf_structsize;
  786. /* Set field size to fixed length, advance */
  787. kp->kf_structsize = sizeof(*kp);
  788. kp++;
  789. }
  790. free(buf);
  791. *cntp = cnt;
  792. return (kif); /* Caller must free() return value */
  793. }
  794. static struct filestat_list *
  795. procstat_getfiles_sysctl(struct procstat *procstat, struct kinfo_proc *kp,
  796. int mmapped)
  797. {
  798. struct kinfo_file *kif, *files;
  799. struct kinfo_vmentry *kve, *vmentries;
  800. struct filestat_list *head;
  801. struct filestat *entry;
  802. char *path;
  803. off_t offset;
  804. int cnt, fd, fflags;
  805. int i, type, uflags;
  806. int refcount;
  807. cap_rights_t cap_rights;
  808. assert(kp);
  809. switch (procstat->type) {
  810. case PROCSTAT_SYSCTL:
  811. files = kinfo_getfile(kp->ki_pid, &cnt);
  812. break;
  813. case PROCSTAT_CORE:
  814. files = kinfo_getfile_core(procstat->core, &cnt);
  815. break;
  816. default:
  817. assert(!"invalid type");
  818. }
  819. if (files == NULL && errno != EPERM) {
  820. warn("kinfo_getfile()");
  821. return (NULL);
  822. }
  823. procstat->files = files;
  824. /*
  825. * Allocate list head.
  826. */
  827. head = malloc(sizeof(*head));
  828. if (head == NULL)
  829. return (NULL);
  830. STAILQ_INIT(head);
  831. for (i = 0; i < cnt; i++) {
  832. kif = &files[i];
  833. type = kinfo_type2fst(kif->kf_type);
  834. fd = kif->kf_fd >= 0 ? kif->kf_fd : -1;
  835. fflags = kinfo_fflags2fst(kif->kf_flags);
  836. uflags = kinfo_uflags2fst(kif->kf_fd);
  837. refcount = kif->kf_ref_count;
  838. offset = kif->kf_offset;
  839. if (*kif->kf_path != '\0')
  840. path = strdup(kif->kf_path);
  841. else
  842. path = NULL;
  843. cap_rights = kif->kf_cap_rights;
  844. /*
  845. * Create filestat entry.
  846. */
  847. entry = filestat_new_entry(kif, type, fd, fflags, uflags,
  848. refcount, offset, path, &cap_rights);
  849. if (entry != NULL)
  850. STAILQ_INSERT_TAIL(head, entry, next);
  851. }
  852. if (mmapped != 0) {
  853. vmentries = procstat_getvmmap(procstat, kp, &cnt);
  854. procstat->vmentries = vmentries;
  855. if (vmentries == NULL || cnt == 0)
  856. goto fail;
  857. for (i = 0; i < cnt; i++) {
  858. kve = &vmentries[i];
  859. if (kve->kve_type != KVME_TYPE_VNODE)
  860. continue;
  861. fflags = 0;
  862. if (kve->kve_protection & KVME_PROT_READ)
  863. fflags = PS_FST_FFLAG_READ;
  864. if ((kve->kve_flags & KVME_FLAG_COW) == 0 &&
  865. kve->kve_protection & KVME_PROT_WRITE)
  866. fflags |= PS_FST_FFLAG_WRITE;
  867. offset = kve->kve_offset;
  868. refcount = kve->kve_ref_count;
  869. if (*kve->kve_path != '\0')
  870. path = strdup(kve->kve_path);
  871. else
  872. path = NULL;
  873. entry = filestat_new_entry(kve, PS_FST_TYPE_VNODE, -1,
  874. fflags, PS_FST_UFLAG_MMAP, refcount, offset, path,
  875. NULL);
  876. if (entry != NULL)
  877. STAILQ_INSERT_TAIL(head, entry, next);
  878. }
  879. }
  880. fail:
  881. return (head);
  882. }
  883. int
  884. procstat_get_pipe_info(struct procstat *procstat, struct filestat *fst,
  885. struct pipestat *ps, char *errbuf)
  886. {
  887. assert(ps);
  888. if (procstat->type == PROCSTAT_KVM) {
  889. return (procstat_get_pipe_info_kvm(procstat->kd, fst, ps,
  890. errbuf));
  891. } else if (procstat->type == PROCSTAT_SYSCTL ||
  892. procstat->type == PROCSTAT_CORE) {
  893. return (procstat_get_pipe_info_sysctl(fst, ps, errbuf));
  894. } else {
  895. warnx("unknown access method: %d", procstat->type);
  896. if (errbuf != NULL)
  897. snprintf(errbuf, _POSIX2_LINE_MAX, "error");
  898. return (1);
  899. }
  900. }
  901. static int
  902. procstat_get_pipe_info_kvm(kvm_t *kd, struct filestat *fst,
  903. struct pipestat *ps, char *errbuf)
  904. {
  905. struct pipe pi;
  906. void *pipep;
  907. assert(kd);
  908. assert(ps);
  909. assert(fst);
  910. bzero(ps, sizeof(*ps));
  911. pipep = fst->fs_typedep;
  912. if (pipep == NULL)
  913. goto fail;
  914. if (!kvm_read_all(kd, (unsigned long)pipep, &pi, sizeof(struct pipe))) {
  915. warnx("can't read pipe at %p", (void *)pipep);
  916. goto fail;
  917. }
  918. ps->addr = (uintptr_t)pipep;
  919. ps->peer = (uintptr_t)pi.pipe_peer;
  920. ps->buffer_cnt = pi.pipe_buffer.cnt;
  921. return (0);
  922. fail:
  923. if (errbuf != NULL)
  924. snprintf(errbuf, _POSIX2_LINE_MAX, "error");
  925. return (1);
  926. }
  927. static int
  928. procstat_get_pipe_info_sysctl(struct filestat *fst, struct pipestat *ps,
  929. char *errbuf __unused)
  930. {
  931. struct kinfo_file *kif;
  932. assert(ps);
  933. assert(fst);
  934. bzero(ps, sizeof(*ps));
  935. kif = fst->fs_typedep;
  936. if (kif == NULL)
  937. return (1);
  938. ps->addr = kif->kf_un.kf_pipe.kf_pipe_addr;
  939. ps->peer = kif->kf_un.kf_pipe.kf_pipe_peer;
  940. ps->buffer_cnt = kif->kf_un.kf_pipe.kf_pipe_buffer_cnt;
  941. return (0);
  942. }
  943. int
  944. procstat_get_pts_info(struct procstat *procstat, struct filestat *fst,
  945. struct ptsstat *pts, char *errbuf)
  946. {
  947. assert(pts);
  948. if (procstat->type == PROCSTAT_KVM) {
  949. return (procstat_get_pts_info_kvm(procstat->kd, fst, pts,
  950. errbuf));
  951. } else if (procstat->type == PROCSTAT_SYSCTL ||
  952. procstat->type == PROCSTAT_CORE) {
  953. return (procstat_get_pts_info_sysctl(fst, pts, errbuf));
  954. } else {
  955. warnx("unknown access method: %d", procstat->type);
  956. if (errbuf != NULL)
  957. snprintf(errbuf, _POSIX2_LINE_MAX, "error");
  958. return (1);
  959. }
  960. }
  961. static int
  962. procstat_get_pts_info_kvm(kvm_t *kd, struct filestat *fst,
  963. struct ptsstat *pts, char *errbuf)
  964. {
  965. struct tty tty;
  966. void *ttyp;
  967. assert(kd);
  968. assert(pts);
  969. assert(fst);
  970. bzero(pts, sizeof(*pts));
  971. ttyp = fst->fs_typedep;
  972. if (ttyp == NULL)
  973. goto fail;
  974. if (!kvm_read_all(kd, (unsigned long)ttyp, &tty, sizeof(struct tty))) {
  975. warnx("can't read tty at %p", (void *)ttyp);
  976. goto fail;
  977. }
  978. pts->dev = dev2udev(kd, tty.t_dev);
  979. (void)kdevtoname(kd, tty.t_dev, pts->devname);
  980. return (0);
  981. fail:
  982. if (errbuf != NULL)
  983. snprintf(errbuf, _POSIX2_LINE_MAX, "error");
  984. return (1);
  985. }
  986. static int
  987. procstat_get_pts_info_sysctl(struct filestat *fst, struct ptsstat *pts,
  988. char *errbuf __unused)
  989. {
  990. struct kinfo_file *kif;
  991. assert(pts);
  992. assert(fst);
  993. bzero(pts, sizeof(*pts));
  994. kif = fst->fs_typedep;
  995. if (kif == NULL)
  996. return (0);
  997. pts->dev = kif->kf_un.kf_pts.kf_pts_dev;
  998. strlcpy(pts->devname, kif->kf_path, sizeof(pts->devname));
  999. return (0);
  1000. }
  1001. int
  1002. procstat_get_sem_info(struct procstat *procstat, struct filestat *fst,
  1003. struct semstat *sem, char *errbuf)
  1004. {
  1005. assert(sem);
  1006. if (procstat->type == PROCSTAT_KVM) {
  1007. return (procstat_get_sem_info_kvm(procstat->kd, fst, sem,
  1008. errbuf));
  1009. } else if (procstat->type == PROCSTAT_SYSCTL ||
  1010. procstat->type == PROCSTAT_CORE) {
  1011. return (procstat_get_sem_info_sysctl(fst, sem, errbuf));
  1012. } else {
  1013. warnx("unknown access method: %d", procstat->type);
  1014. if (errbuf != NULL)
  1015. snprintf(errbuf, _POSIX2_LINE_MAX, "error");
  1016. return (1);
  1017. }
  1018. }
  1019. static int
  1020. procstat_get_sem_info_kvm(kvm_t *kd, struct filestat *fst,
  1021. struct semstat *sem, char *errbuf)
  1022. {
  1023. struct ksem ksem;
  1024. void *ksemp;
  1025. char *path;
  1026. int i;
  1027. assert(kd);
  1028. assert(sem);
  1029. assert(fst);
  1030. bzero(sem, sizeof(*sem));
  1031. ksemp = fst->fs_typedep;
  1032. if (ksemp == NULL)
  1033. goto fail;
  1034. if (!kvm_read_all(kd, (unsigned long)ksemp, &ksem,
  1035. sizeof(struct ksem))) {
  1036. warnx("can't read ksem at %p", (void *)ksemp);
  1037. goto fail;
  1038. }
  1039. sem->mode = S_IFREG | ksem.ks_mode;
  1040. sem->value = ksem.ks_value;
  1041. if (fst->fs_path == NULL && ksem.ks_path != NULL) {
  1042. path = malloc(MAXPATHLEN);
  1043. for (i = 0; i < MAXPATHLEN - 1; i++) {
  1044. if (!kvm_read_all(kd, (unsigned long)ksem.ks_path + i,
  1045. path + i, 1))
  1046. break;
  1047. if (path[i] == '\0')
  1048. break;
  1049. }
  1050. path[i] = '\0';
  1051. if (i == 0)
  1052. free(path);
  1053. else
  1054. fst->fs_path = path;
  1055. }
  1056. return (0);
  1057. fail:
  1058. if (errbuf != NULL)
  1059. snprintf(errbuf, _POSIX2_LINE_MAX, "error");
  1060. return (1);
  1061. }
  1062. static int
  1063. procstat_get_sem_info_sysctl(struct filestat *fst, struct semstat *sem,
  1064. char *errbuf __unused)
  1065. {
  1066. struct kinfo_file *kif;
  1067. assert(sem);
  1068. assert(fst);
  1069. bzero(sem, sizeof(*sem));
  1070. kif = fst->fs_typedep;
  1071. if (kif == NULL)
  1072. return (0);
  1073. sem->value = kif->kf_un.kf_sem.kf_sem_value;
  1074. sem->mode = kif->kf_un.kf_sem.kf_sem_mode;
  1075. return (0);
  1076. }
  1077. int
  1078. procstat_get_shm_info(struct procstat *procstat, struct filestat *fst,
  1079. struct shmstat *shm, char *errbuf)
  1080. {
  1081. assert(shm);
  1082. if (procstat->type == PROCSTAT_KVM) {
  1083. return (procstat_get_shm_info_kvm(procstat->kd, fst, shm,
  1084. errbuf));
  1085. } else if (procstat->type == PROCSTAT_SYSCTL ||
  1086. procstat->type == PROCSTAT_CORE) {
  1087. return (procstat_get_shm_info_sysctl(fst, shm, errbuf));
  1088. } else {
  1089. warnx("unknown access method: %d", procstat->type);
  1090. if (errbuf != NULL)
  1091. snprintf(errbuf, _POSIX2_LINE_MAX, "error");
  1092. return (1);
  1093. }
  1094. }
  1095. static int
  1096. procstat_get_shm_info_kvm(kvm_t *kd, struct filestat *fst,
  1097. struct shmstat *shm, char *errbuf)
  1098. {
  1099. struct shmfd shmfd;
  1100. void *shmfdp;
  1101. char *path;
  1102. int i;
  1103. assert(kd);
  1104. assert(shm);
  1105. assert(fst);
  1106. bzero(shm, sizeof(*shm));
  1107. shmfdp = fst->fs_typedep;
  1108. if (shmfdp == NULL)
  1109. goto fail;
  1110. if (!kvm_read_all(kd, (unsigned long)shmfdp, &shmfd,
  1111. sizeof(struct shmfd))) {
  1112. warnx("can't read shmfd at %p", (void *)shmfdp);
  1113. goto fail;
  1114. }
  1115. shm->mode = S_IFREG | shmfd.shm_mode;
  1116. shm->size = shmfd.shm_size;
  1117. if (fst->fs_path == NULL && shmfd.shm_path != NULL) {
  1118. path = malloc(MAXPATHLEN);
  1119. for (i = 0; i < MAXPATHLEN - 1; i++) {
  1120. if (!kvm_read_all(kd, (unsigned long)shmfd.shm_path + i,
  1121. path + i, 1))
  1122. break;
  1123. if (path[i] == '\0')
  1124. break;
  1125. }
  1126. path[i] = '\0';
  1127. if (i == 0)
  1128. free(path);
  1129. else
  1130. fst->fs_path = path;
  1131. }
  1132. return (0);
  1133. fail:
  1134. if (errbuf != NULL)
  1135. snprintf(errbuf, _POSIX2_LINE_MAX, "error");
  1136. return (1);
  1137. }
  1138. static int
  1139. procstat_get_shm_info_sysctl(struct filestat *fst, struct shmstat *shm,
  1140. char *errbuf __unused)
  1141. {
  1142. struct kinfo_file *kif;
  1143. assert(shm);
  1144. assert(fst);
  1145. bzero(shm, sizeof(*shm));
  1146. kif = fst->fs_typedep;
  1147. if (kif == NULL)
  1148. return (0);
  1149. shm->size = kif->kf_un.kf_file.kf_file_size;
  1150. shm->mode = kif->kf_un.kf_file.kf_file_mode;
  1151. return (0);
  1152. }
  1153. int
  1154. procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst,
  1155. struct vnstat *vn, char *errbuf)
  1156. {
  1157. assert(vn);
  1158. if (procstat->type == PROCSTAT_KVM) {
  1159. return (procstat_get_vnode_info_kvm(procstat->kd, fst, vn,
  1160. errbuf));
  1161. } else if (procstat->type == PROCSTAT_SYSCTL ||
  1162. procstat->type == PROCSTAT_CORE) {
  1163. return (procstat_get_vnode_info_sysctl(fst, vn, errbuf));
  1164. } else {
  1165. warnx("unknown access method: %d", procstat->type);
  1166. if (errbuf != NULL)
  1167. snprintf(errbuf, _POSIX2_LINE_MAX, "error");
  1168. return (1);
  1169. }
  1170. }
  1171. static int
  1172. procstat_get_vnode_info_kvm(kvm_t *kd, struct filestat *fst,
  1173. struct vnstat *vn, char *errbuf)
  1174. {
  1175. /* Filesystem specific handlers. */
  1176. #define FSTYPE(fst) {#fst, fst##_filestat}
  1177. struct {
  1178. const char *tag;
  1179. int (*handler)(kvm_t *kd, struct vnode *vp,
  1180. struct vnstat *vn);
  1181. } fstypes[] = {
  1182. FSTYPE(devfs),
  1183. FSTYPE(isofs),
  1184. FSTYPE(msdosfs),
  1185. FSTYPE(nfs),
  1186. FSTYPE(smbfs),
  1187. FSTYPE(udf),
  1188. FSTYPE(ufs),
  1189. #ifdef LIBPROCSTAT_ZFS
  1190. FSTYPE(zfs),
  1191. #endif
  1192. };
  1193. #define NTYPES (sizeof(fstypes) / sizeof(*fstypes))
  1194. struct vnode vnode;
  1195. char tagstr[12];
  1196. void *vp;
  1197. int error;
  1198. unsigned int i;
  1199. assert(kd);
  1200. assert(vn);
  1201. assert(fst);
  1202. vp = fst->fs_typedep;
  1203. if (vp == NULL)
  1204. goto fail;
  1205. error = kvm_read_all(kd, (unsigned long)vp, &vnode, sizeof(vnode));
  1206. if (error == 0) {
  1207. warnx("can't read vnode at %p", (void *)vp);
  1208. goto fail;
  1209. }
  1210. bzero(vn, sizeof(*vn));
  1211. vn->vn_type = vntype2psfsttype(vnode.v_type);
  1212. if (vnode.v_type == VNON || vnode.v_type == VBAD)
  1213. return (0);
  1214. error = kvm_read_all(kd, (unsigned long)vnode.v_lock.lock_object.lo_name,
  1215. tagstr, sizeof(tagstr));
  1216. if (error == 0) {
  1217. warnx("can't read lo_name at %p", (void *)vp);
  1218. goto fail;
  1219. }
  1220. tagstr[sizeof(tagstr) - 1] = '\0';
  1221. /*
  1222. * Find appropriate handler.
  1223. */
  1224. for (i = 0; i < NTYPES; i++)
  1225. if (!strcmp(fstypes[i].tag, tagstr)) {
  1226. if (fstypes[i].handler(kd, &vnode, vn) != 0) {
  1227. goto fail;
  1228. }
  1229. break;
  1230. }
  1231. if (i == NTYPES) {
  1232. if (errbuf != NULL)
  1233. snprintf(errbuf, _POSIX2_LINE_MAX, "?(%s)", tagstr);
  1234. return (1);
  1235. }
  1236. vn->vn_mntdir = getmnton(kd, vnode.v_mount);
  1237. if ((vnode.v_type == VBLK || vnode.v_type == VCHR) &&
  1238. vnode.v_rdev != NULL){
  1239. vn->vn_dev = dev2udev(kd, vnode.v_rdev);
  1240. (void)kdevtoname(kd, vnode.v_rdev, vn->vn_devname);
  1241. } else {
  1242. vn->vn_dev = -1;
  1243. }
  1244. return (0);
  1245. fail:
  1246. if (errbuf != NULL)
  1247. snprintf(errbuf, _POSIX2_LINE_MAX, "error");
  1248. return (1);
  1249. }
  1250. /*
  1251. * kinfo vnode type to filestat translation.
  1252. */
  1253. static int
  1254. kinfo_vtype2fst(int kfvtype)
  1255. {
  1256. static struct {
  1257. int kf_vtype;
  1258. int fst_vtype;
  1259. } kfvtypes2fst[] = {
  1260. { KF_VTYPE_VBAD, PS_FST_VTYPE_VBAD },
  1261. { KF_VTYPE_VBLK, PS_FST_VTYPE_VBLK },
  1262. { KF_VTYPE_VCHR, PS_FST_VTYPE_VCHR },
  1263. { KF_VTYPE_VDIR, PS_FST_VTYPE_VDIR },
  1264. { KF_VTYPE_VFIFO, PS_FST_VTYPE_VFIFO },
  1265. { KF_VTYPE_VLNK, PS_FST_VTYPE_VLNK },
  1266. { KF_VTYPE_VNON, PS_FST_VTYPE_VNON },
  1267. { KF_VTYPE_VREG, PS_FST_VTYPE_VREG },
  1268. { KF_VTYPE_VSOCK, PS_FST_VTYPE_VSOCK }
  1269. };
  1270. #define NKFVTYPES (sizeof(kfvtypes2fst) / sizeof(*kfvtypes2fst))
  1271. unsigned int i;
  1272. for (i = 0; i < NKFVTYPES; i++)
  1273. if (kfvtypes2fst[i].kf_vtype == kfvtype)
  1274. break;
  1275. if (i == NKFVTYPES)
  1276. return (PS_FST_VTYPE_UNKNOWN);
  1277. return (kfvtypes2fst[i].fst_vtype);
  1278. }
  1279. static int
  1280. procstat_get_vnode_info_sysctl(struct filestat *fst, struct vnstat *vn,
  1281. char *errbuf)
  1282. {
  1283. struct statfs stbuf;
  1284. struct kinfo_file *kif;
  1285. struct kinfo_vmentry *kve;
  1286. char *name, *path;
  1287. uint64_t fileid;
  1288. uint64_t size;
  1289. uint64_t fsid;
  1290. uint64_t rdev;
  1291. uint16_t mode;
  1292. int vntype;
  1293. int status;
  1294. assert(fst);
  1295. assert(vn);
  1296. bzero(vn, sizeof(*vn));
  1297. if (fst->fs_typedep == NULL)
  1298. return (1);
  1299. if (fst->fs_uflags & PS_FST_UFLAG_MMAP) {
  1300. kve = fst->fs_typedep;
  1301. fileid = kve->kve_vn_fileid;
  1302. fsid = kve->kve_vn_fsid;
  1303. mode = kve->kve_vn_mode;
  1304. path = kve->kve_path;
  1305. rdev = kve->kve_vn_rdev;
  1306. size = kve->kve_vn_size;
  1307. vntype = kinfo_vtype2fst(kve->kve_vn_type);
  1308. status = kve->kve_status;
  1309. } else {
  1310. kif = fst->fs_typedep;
  1311. fileid = kif->kf_un.kf_file.kf_file_fileid;
  1312. fsid = kif->kf_un.kf_file.kf_file_fsid;
  1313. mode = kif->kf_un.kf_file.kf_file_mode;
  1314. path = kif->kf_path;
  1315. rdev = kif->kf_un.kf_file.kf_file_rdev;
  1316. size = kif->kf_un.kf_file.kf_file_size;
  1317. vntype = kinfo_vtype2fst(kif->kf_vnode_type);
  1318. status = kif->kf_status;
  1319. }
  1320. vn->vn_type = vntype;
  1321. if (vntype == PS_FST_VTYPE_VNON || vntype == PS_FST_VTYPE_VBAD)
  1322. return (0);
  1323. if ((status & KF_ATTR_VALID) == 0) {
  1324. if (errbuf != NULL) {
  1325. snprintf(errbuf, _POSIX2_LINE_MAX,
  1326. "? (no info available)");
  1327. }
  1328. return (1);
  1329. }
  1330. if (path && *path) {
  1331. statfs(path, &stbuf);
  1332. vn->vn_mntdir = strdup(stbuf.f_mntonname);
  1333. } else
  1334. vn->vn_mntdir = strdup("-");
  1335. vn->vn_dev = rdev;
  1336. if (vntype == PS_FST_VTYPE_VBLK) {
  1337. name = devname(rdev, S_IFBLK);
  1338. if (name != NULL)
  1339. strlcpy(vn->vn_devname, name,
  1340. sizeof(vn->vn_devname));
  1341. } else if (vntype == PS_FST_VTYPE_VCHR) {
  1342. name = devname(vn->vn_dev, S_IFCHR);
  1343. if (name != NULL)
  1344. strlcpy(vn->vn_devname, name,
  1345. sizeof(vn->vn_devname));
  1346. }
  1347. vn->vn_fsid = fsid;
  1348. vn->vn_fileid = fileid;
  1349. vn->vn_size = size;
  1350. vn->vn_mode = mode;
  1351. return (0);
  1352. }
  1353. int
  1354. procstat_get_socket_info(struct procstat *procstat, struct filestat *fst,
  1355. struct sockstat *sock, char *errbuf)
  1356. {
  1357. assert(sock);
  1358. if (procstat->type == PROCSTAT_KVM) {
  1359. return (procstat_get_socket_info_kvm(procstat->kd, fst, sock,
  1360. errbuf));
  1361. } else if (procstat->type == PROCSTAT_SYSCTL ||
  1362. procstat->type == PROCSTAT_CORE) {
  1363. return (procstat_get_socket_info_sysctl(fst, sock, errbuf));
  1364. } else {
  1365. warnx("unknown access method: %d", procstat->type);
  1366. if (errbuf != NULL)
  1367. snprintf(errbuf, _POSIX2_LINE_MAX, "error");
  1368. return (1);
  1369. }
  1370. }
  1371. static int
  1372. procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst,
  1373. struct sockstat *sock, char *errbuf)
  1374. {
  1375. struct domain dom;
  1376. struct protosw proto;
  1377. struct socket s;
  1378. struct unpcb unpcb;
  1379. ssize_t len;
  1380. void *so;
  1381. assert(kd);
  1382. assert(sock);
  1383. assert(fst);
  1384. bzero(sock, sizeof(*sock));
  1385. so = fst->fs_typedep;
  1386. if (so == NULL)
  1387. goto fail;
  1388. sock->so_addr = (uintptr_t)so;
  1389. /* fill in socket */
  1390. if (!kvm_read_all(kd, (unsigned long)so, &s,
  1391. sizeof(struct socket))) {
  1392. warnx("can't read sock at %p", (void *)so);
  1393. goto fail;
  1394. }
  1395. /* fill in protosw entry */
  1396. if (!kvm_read_all(kd, (unsigned long)s.so_proto, &proto,
  1397. sizeof(struct protosw))) {
  1398. warnx("can't read protosw at %p", (void *)s.so_proto);
  1399. goto fail;
  1400. }
  1401. /* fill in domain */
  1402. if (!kvm_read_all(kd, (unsigned long)proto.pr_domain, &dom,
  1403. sizeof(struct domain))) {
  1404. warnx("can't read domain at %p",
  1405. (void *)proto.pr_domain);
  1406. goto fail;
  1407. }
  1408. if ((len = kvm_read(kd, (unsigned long)dom.dom_name, sock->dname,
  1409. sizeof(sock->dname) - 1)) < 0) {
  1410. warnx("can't read domain name at %p", (void *)dom.dom_name);
  1411. sock->dname[0] = '\0';
  1412. }
  1413. else
  1414. sock->dname[len] = '\0';
  1415. /*
  1416. * Fill in known data.
  1417. */
  1418. sock->type = s.so_type;
  1419. sock->proto = proto.pr_protocol;
  1420. sock->dom_family = dom.dom_family;
  1421. sock->so_pcb = (uintptr_t)s.so_pcb;
  1422. sock->sendq = s.so_snd.sb_ccc;
  1423. sock->recvq = s.so_rcv.sb_ccc;
  1424. sock->so_rcv_sb_state = s.so_rcv.sb_state;
  1425. sock->so_snd_sb_state = s.so_snd.sb_state;
  1426. /*
  1427. * Protocol specific data.
  1428. */
  1429. switch (dom.dom_family) {
  1430. case AF_UNIX:
  1431. if (s.so_pcb) {
  1432. if (kvm_read(kd, (u_long)s.so_pcb, (char *)&unpcb,
  1433. sizeof(struct unpcb)) != sizeof(struct unpcb)){
  1434. warnx("can't read unpcb at %p",
  1435. (void *)s.so_pcb);
  1436. } else if (unpcb.unp_conn) {
  1437. sock->unp_conn = (uintptr_t)unpcb.unp_conn;
  1438. }
  1439. }
  1440. break;
  1441. default:
  1442. break;
  1443. }
  1444. return (0);
  1445. fail:
  1446. if (errbuf != NULL)
  1447. snprintf(errbuf, _POSIX2_LINE_MAX, "error");
  1448. return (1);
  1449. }
  1450. static int
  1451. procstat_get_socket_info_sysctl(struct filestat *fst, struct sockstat *sock,
  1452. char *errbuf __unused)
  1453. {
  1454. struct kinfo_file *kif;
  1455. assert(sock);
  1456. assert(fst);
  1457. bzero(sock, sizeof(*sock));
  1458. kif = fst->fs_typedep;
  1459. if (kif == NULL)
  1460. return (0);
  1461. /*
  1462. * Fill in known data.
  1463. */
  1464. sock->type = kif->kf_sock_type;
  1465. sock->proto = kif->kf_sock_protocol;
  1466. sock->dom_family = kif->kf_sock_domain;
  1467. sock->so_pcb = kif->kf_un.kf_sock.kf_sock_pcb;
  1468. strlcpy(sock->dname, kif->kf_path, sizeof(sock->dname));
  1469. bcopy(&kif->kf_un.kf_sock.kf_sa_local, &sock->sa_local,
  1470. kif->kf_un.kf_sock.kf_sa_local.ss_len);
  1471. bcopy(&kif->kf_un.kf_sock.kf_sa_peer, &sock->sa_peer,
  1472. kif->kf_un.kf_sock.kf_sa_peer.ss_len);
  1473. /*
  1474. * Protocol specific data.
  1475. */
  1476. switch (sock->dom_family) {
  1477. case AF_INET:
  1478. case AF_INET6:
  1479. if (sock->proto == IPPROTO_TCP) {
  1480. sock->sendq = kif->kf_un.kf_sock.kf_sock_sendq;
  1481. sock->recvq = kif->kf_un.kf_sock.kf_sock_recvq;
  1482. }
  1483. break;
  1484. case AF_UNIX:
  1485. if (kif->kf_un.kf_sock.kf_sock_unpconn != 0) {
  1486. sock->so_rcv_sb_state =
  1487. kif->kf_un.kf_sock.kf_sock_rcv_sb_state;
  1488. sock->so_snd_sb_state =
  1489. kif->kf_un.kf_sock.kf_sock_snd_sb_state;
  1490. sock->unp_conn =
  1491. kif->kf_un.kf_sock.kf_sock_unpconn;
  1492. sock->sendq = kif->kf_un.kf_sock.kf_sock_sendq;
  1493. sock->recvq = kif->kf_un.kf_sock.kf_sock_recvq;
  1494. }
  1495. break;
  1496. default:
  1497. break;
  1498. }
  1499. return (0);
  1500. }
  1501. /*
  1502. * Descriptor flags to filestat translation.
  1503. */
  1504. static int
  1505. to_filestat_flags(int flags)
  1506. {
  1507. static struct {
  1508. int flag;
  1509. int fst_flag;
  1510. } fstflags[] = {
  1511. { FREAD, PS_FST_FFLAG_READ },
  1512. { FWRITE, PS_FST_FFLAG_WRITE },
  1513. { O_APPEND, PS_FST_FFLAG_APPEND },
  1514. { O_ASYNC, PS_FST_FFLAG_ASYNC },
  1515. { O_CREAT, PS_FST_FFLAG_CREAT },
  1516. { O_DIRECT, PS_FST_FFLAG_DIRECT },
  1517. { O_EXCL, PS_FST_FFLAG_EXCL },
  1518. { O_EXEC, PS_FST_FFLAG_EXEC },
  1519. { O_EXLOCK, PS_FST_FFLAG_EXLOCK },
  1520. { O_NOFOLLOW, PS_FST_FFLAG_NOFOLLOW },
  1521. { O_NONBLOCK, PS_FST_FFLAG_NONBLOCK },
  1522. { O_SHLOCK, PS_FST_FFLAG_SHLOCK },
  1523. { O_SYNC, PS_FST_FFLAG_SYNC },
  1524. { O_TRUNC, PS_FST_FFLAG_TRUNC }
  1525. };
  1526. #define NFSTFLAGS (sizeof(fstflags) / sizeof(*fstflags))
  1527. int fst_flags;
  1528. unsigned int i;
  1529. fst_flags = 0;
  1530. for (i = 0; i < NFSTFLAGS; i++)
  1531. if (flags & fstflags[i].flag)
  1532. fst_flags |= fstflags[i].fst_flag;
  1533. return (fst_flags);
  1534. }
  1535. /*
  1536. * Vnode type to filestate translation.
  1537. */
  1538. static int
  1539. vntype2psfsttype(int type)
  1540. {
  1541. static struct {
  1542. int vtype;
  1543. int fst_vtype;
  1544. } vt2fst[] = {
  1545. { VBAD, PS_FST_VTYPE_VBAD },
  1546. { VBLK, PS_FST_VTYPE_VBLK },
  1547. { VCHR, PS_FST_VTYPE_VCHR },
  1548. { VDIR, PS_FST_VTYPE_VDIR },
  1549. { VFIFO, PS_FST_VTYPE_VFIFO },
  1550. { VLNK, PS_FST_VTYPE_VLNK },
  1551. { VNON, PS_FST_VTYPE_VNON },
  1552. { VREG, PS_FST_VTYPE_VREG },
  1553. { VSOCK, PS_FST_VTYPE_VSOCK }
  1554. };
  1555. #define NVFTYPES (sizeof(vt2fst) / sizeof(*vt2fst))
  1556. unsigned int i, fst_type;
  1557. fst_type = PS_FST_VTYPE_UNKNOWN;
  1558. for (i = 0; i < NVFTYPES; i++) {
  1559. if (type == vt2fst[i].vtype) {
  1560. fst_type = vt2fst[i].fst_vtype;
  1561. break;
  1562. }
  1563. }
  1564. return (fst_type);
  1565. }
  1566. static char *
  1567. getmnton(kvm_t *kd, struct mount *m)
  1568. {
  1569. struct mount mnt;
  1570. static struct mtab {
  1571. struct mtab *next;
  1572. struct mount *m;
  1573. char mntonname[MNAMELEN + 1];
  1574. } *mhead = NULL;
  1575. struct mtab *mt;
  1576. for (mt = mhead; mt != NULL; mt = mt->next)
  1577. if (m == mt->m)
  1578. return (mt->mntonname);
  1579. if (!kvm_read_all(kd, (unsigned long)m, &mnt, sizeof(struct mount))) {
  1580. warnx("can't read mount table at %p", (void *)m);
  1581. return (NULL);
  1582. }
  1583. if ((mt = malloc(sizeof (struct mtab))) == NULL)
  1584. err(1, NULL);
  1585. mt->m = m;
  1586. bcopy(&mnt.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN);
  1587. mt->mntonname[MNAMELEN] = '\0';
  1588. mt->next = mhead;
  1589. mhead = mt;
  1590. return (mt->mntonname);
  1591. }
  1592. /*
  1593. * Auxiliary structures and functions to get process environment or
  1594. * command line arguments.
  1595. */
  1596. struct argvec {
  1597. char *buf;
  1598. size_t bufsize;
  1599. char **argv;
  1600. size_t argc;
  1601. };
  1602. static struct argvec *
  1603. argvec_alloc(size_t bufsize)
  1604. {
  1605. struct argvec *av;
  1606. av = malloc(sizeof(*av));
  1607. if (av == NULL)
  1608. return (NULL);
  1609. av->bufsize = bufsize;
  1610. av->buf = malloc(av->bufsize);
  1611. if (av->buf == NULL) {
  1612. free(av);
  1613. return (NULL);
  1614. }
  1615. av->argc = 32;
  1616. av->argv = malloc(sizeof(char *) * av->argc);
  1617. if (av->argv == NULL) {
  1618. free(av->buf);
  1619. free(av);
  1620. return (NULL);
  1621. }
  1622. return av;
  1623. }
  1624. static void
  1625. argvec_free(struct argvec * av)
  1626. {
  1627. free(av->argv);
  1628. free(av->buf);
  1629. free(av);
  1630. }
  1631. static char **
  1632. getargv(struct procstat *procstat, struct kinfo_proc *kp, size_t nchr, int env)
  1633. {
  1634. int error, name[4], argc, i;
  1635. struct argvec *av, **avp;
  1636. enum psc_type type;
  1637. size_t len;
  1638. char *p, **argv;
  1639. assert(procstat);
  1640. assert(kp);
  1641. if (procstat->type == PROCSTAT_KVM) {
  1642. warnx("can't use kvm access method");
  1643. return (NULL);
  1644. }
  1645. if (procstat->type != PROCSTAT_SYSCTL &&
  1646. procstat->type != PROCSTAT_CORE) {
  1647. warnx("unknown access method: %d", procstat->type);
  1648. return (NULL);
  1649. }
  1650. if (nchr == 0 || nchr > ARG_MAX)
  1651. nchr = ARG_MAX;
  1652. avp = (struct argvec **)(env ? &procstat->argv : &procstat->envv);
  1653. av = *avp;
  1654. if (av == NULL)
  1655. {
  1656. av = argvec_alloc(nchr);
  1657. if (av == NULL)
  1658. {
  1659. warn("malloc(%zu)", nchr);
  1660. return (NULL);
  1661. }
  1662. *avp = av;
  1663. } else if (av->bufsize < nchr) {
  1664. av->buf = reallocf(av->buf, nchr);
  1665. if (av->buf == NULL) {
  1666. warn("malloc(%zu)", nchr);
  1667. return (NULL);
  1668. }
  1669. }
  1670. if (procstat->type == PROCSTAT_SYSCTL) {
  1671. name[0] = CTL_KERN;
  1672. name[1] = KERN_PROC;
  1673. name[2] = env ? KERN_PROC_ENV : KERN_PROC_ARGS;
  1674. name[3] = kp->ki_pid;
  1675. len = nchr;
  1676. error = sysctl(name, nitems(name), av->buf, &len, NULL, 0);
  1677. if (error != 0 && errno != ESRCH && errno != EPERM)
  1678. warn("sysctl(kern.proc.%s)", env ? "env" : "args");
  1679. if (error != 0 || len == 0)
  1680. return (NULL);
  1681. } else /* procstat->type == PROCSTAT_CORE */ {
  1682. type = env ? PSC_TYPE_ENVV : PSC_TYPE_ARGV;
  1683. len = nchr;
  1684. if (procstat_core_get(procstat->core, type, av->buf, &len)
  1685. == NULL) {
  1686. return (NULL);
  1687. }
  1688. }
  1689. argv = av->argv;
  1690. argc = av->argc;
  1691. i = 0;
  1692. for (p = av->buf; p < av->buf + len; p += strlen(p) + 1) {
  1693. argv[i++] = p;
  1694. if (i < argc)
  1695. continue;
  1696. /* Grow argv. */
  1697. argc += argc;
  1698. argv = realloc(argv, sizeof(char *) * argc);
  1699. if (argv == NULL) {
  1700. warn("malloc(%zu)", sizeof(char *) * argc);
  1701. return (NULL);
  1702. }
  1703. av->argv = argv;
  1704. av->argc = argc;
  1705. }
  1706. argv[i] = NULL;
  1707. return (argv);
  1708. }
  1709. /*
  1710. * Return process command line arguments.
  1711. */
  1712. char **
  1713. procstat_getargv(struct procstat *procstat, struct kinfo_proc *p, size_t nchr)
  1714. {
  1715. return (getargv(procstat, p, nchr, 0));
  1716. }
  1717. /*
  1718. * Free the buffer allocated by procstat_getargv().
  1719. */
  1720. void
  1721. procstat_freeargv(struct procstat *procstat)
  1722. {
  1723. if (procstat->argv != NULL) {
  1724. argvec_free(procstat->argv);
  1725. procstat->argv = NULL;
  1726. }
  1727. }
  1728. /*
  1729. * Return process environment.
  1730. */
  1731. char **
  1732. procstat_getenvv(struct procstat *procstat, struct kinfo_proc *p, size_t nchr)
  1733. {
  1734. return (getargv(procstat, p, nchr, 1));
  1735. }
  1736. /*
  1737. * Free the buffer allocated by procstat_getenvv().
  1738. */
  1739. void
  1740. procstat_freeenvv(struct procstat *procstat)
  1741. {
  1742. if (procstat->envv != NULL) {
  1743. argvec_free(procstat->envv);
  1744. procstat->envv = NULL;
  1745. }
  1746. }
  1747. static struct kinfo_vmentry *
  1748. kinfo_getvmmap_core(struct procstat_core *core, int *cntp)
  1749. {
  1750. int cnt;
  1751. size_t len;
  1752. char *buf, *bp, *eb;
  1753. struct kinfo_vmentry *kiv, *kp, *kv;
  1754. buf = procstat_core_get(core, PSC_TYPE_VMMAP, NULL, &len);
  1755. if (buf == NULL)
  1756. return (NULL);
  1757. /*
  1758. * XXXMG: The code below is just copy&past from libutil.
  1759. * The code duplication can be avoided if libutil
  1760. * is extended to provide something like:
  1761. * struct kinfo_vmentry *kinfo_getvmmap_from_buf(const char *buf,
  1762. * size_t len, int *cntp);
  1763. */
  1764. /* Pass 1: count items */
  1765. cnt = 0;
  1766. bp = buf;
  1767. eb = buf + len;
  1768. while (bp < eb) {
  1769. kv = (struct kinfo_vmentry *)(uintptr_t)bp;
  1770. if (kv->kve_structsize == 0)
  1771. break;
  1772. bp += kv->kve_structsize;
  1773. cnt++;
  1774. }
  1775. kiv = calloc(cnt, sizeof(*kiv));
  1776. if (kiv == NULL) {
  1777. free(buf);
  1778. return (NULL);
  1779. }
  1780. bp = buf;
  1781. eb = buf + len;
  1782. kp = kiv;
  1783. /* Pass 2: unpack */
  1784. while (bp < eb) {
  1785. kv = (struct kinfo_vmentry *)(uintptr_t)bp;
  1786. if (kv->kve_structsize == 0)
  1787. break;
  1788. /* Copy/expand into pre-zeroed buffer */
  1789. memcpy(kp, kv, kv->kve_structsize);
  1790. /* Advance to next packed record */
  1791. bp += kv->kve_structsize;
  1792. /* Set field size to fixed length, advance */
  1793. kp->kve_structsize = sizeof(*kp);
  1794. kp++;
  1795. }
  1796. free(buf);
  1797. *cntp = cnt;
  1798. return (kiv); /* Caller must free() return value */
  1799. }
  1800. struct kinfo_vmentry *
  1801. procstat_getvmmap(struct procstat *procstat, struct kinfo_proc *kp,
  1802. unsigned int *cntp)
  1803. {
  1804. switch (procstat->type) {
  1805. case PROCSTAT_KVM:
  1806. warnx("kvm method is not supported");
  1807. return (NULL);
  1808. case PROCSTAT_SYSCTL:
  1809. return (kinfo_getvmmap(kp->ki_pid, cntp));
  1810. case PROCSTAT_CORE:
  1811. return (kinfo_getvmmap_core(procstat->core, cntp));
  1812. default:
  1813. warnx("unknown access method: %d", procstat->type);
  1814. return (NULL);
  1815. }
  1816. }
  1817. void
  1818. procstat_freevmmap(struct procstat *procstat __unused,
  1819. struct kinfo_vmentry *vmmap)
  1820. {
  1821. free(vmmap);
  1822. }
  1823. static gid_t *
  1824. procstat_getgroups_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned int *cntp)
  1825. {
  1826. struct proc proc;
  1827. struct ucred ucred;
  1828. gid_t *groups;
  1829. size_t len;
  1830. assert(kd != NULL);
  1831. assert(kp != NULL);
  1832. if (!kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc,
  1833. sizeof(proc))) {
  1834. warnx("can't read proc struct at %p for pid %d",
  1835. kp->ki_paddr, kp->ki_pid);
  1836. return (NULL);
  1837. }
  1838. if (proc.p_ucred == NOCRED)
  1839. return (NULL);
  1840. if (!kvm_read_all(kd, (unsigned long)proc.p_ucred, &ucred,
  1841. sizeof(ucred))) {
  1842. warnx("can't read ucred struct at %p for pid %d",
  1843. proc.p_ucred, kp->ki_pid);
  1844. return (NULL);
  1845. }
  1846. len = ucred.cr_ngroups * sizeof(gid_t);
  1847. groups = malloc(len);
  1848. if (groups == NULL) {
  1849. warn("malloc(%zu)", len);
  1850. return (NULL);
  1851. }
  1852. if (!kvm_read_all(kd, (unsigned long)ucred.cr_groups, groups, len)) {
  1853. warnx("can't read groups at %p for pid %d",
  1854. ucred.cr_groups, kp->ki_pid);
  1855. free(groups);
  1856. return (NULL);
  1857. }
  1858. *cntp = ucred.cr_ngroups;
  1859. return (groups);
  1860. }
  1861. static gid_t *
  1862. procstat_getgroups_sysctl(pid_t pid, unsigned int *cntp)
  1863. {
  1864. int mib[4];
  1865. size_t len;
  1866. gid_t *groups;
  1867. mib[0] = CTL_KERN;
  1868. mib[1] = KERN_PROC;
  1869. mib[2] = KERN_PROC_GROUPS;
  1870. mib[3] = pid;
  1871. len = (sysconf(_SC_NGROUPS_MAX) + 1) * sizeof(gid_t);
  1872. groups = malloc(len);
  1873. if (groups == NULL) {
  1874. warn("malloc(%zu)", len);
  1875. return (NULL);
  1876. }
  1877. if (sysctl(mib, nitems(mib), groups, &len, NULL, 0) == -1) {
  1878. warn("sysctl: kern.proc.groups: %d", pid);
  1879. free(groups);
  1880. return (NULL);
  1881. }
  1882. *cntp = len / sizeof(gid_t);
  1883. return (groups);
  1884. }
  1885. static gid_t *
  1886. procstat_getgroups_core(struct procstat_core *core, unsigned int *cntp)
  1887. {
  1888. size_t len;
  1889. gid_t *groups;
  1890. groups = procstat_core_get(core, PSC_TYPE_GROUPS, NULL, &len);
  1891. if (groups == NULL)
  1892. return (NULL);
  1893. *cntp = len / sizeof(gid_t);
  1894. return (groups);
  1895. }
  1896. gid_t *
  1897. procstat_getgroups(struct procstat *procstat, struct kinfo_proc *kp,
  1898. unsigned int *cntp)
  1899. {
  1900. switch (procstat->type) {
  1901. case PROCSTAT_KVM:
  1902. return (procstat_getgroups_kvm(procstat->kd, kp, cntp));
  1903. case PROCSTAT_SYSCTL:
  1904. return (procstat_getgroups_sysctl(kp->ki_pid, cntp));
  1905. case PROCSTAT_CORE:
  1906. return (procstat_getgroups_core(procstat->core, cntp));
  1907. default:
  1908. warnx("unknown access method: %d", procstat->type);
  1909. return (NULL);
  1910. }
  1911. }
  1912. void
  1913. procstat_freegroups(struct procstat *procstat __unused, gid_t *groups)
  1914. {
  1915. free(groups);
  1916. }
  1917. static int
  1918. procstat_getumask_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned short *maskp)
  1919. {
  1920. struct pwddesc pd;
  1921. assert(kd != NULL);
  1922. assert(kp != NULL);
  1923. if (kp->ki_pd == NULL)
  1924. return (-1);
  1925. if (!kvm_read_all(kd, (unsigned long)kp->ki_pd, &pd, sizeof(pd))) {
  1926. warnx("can't read pwddesc at %p for pid %d", kp->ki_pd,
  1927. kp->ki_pid);
  1928. return (-1);
  1929. }
  1930. *maskp = pd.pd_cmask;
  1931. return (0);
  1932. }
  1933. static int
  1934. procstat_getumask_sysctl(pid_t pid, unsigned short *maskp)
  1935. {
  1936. int error;
  1937. int mib[4];
  1938. size_t len;
  1939. mib[0] = CTL_KERN;
  1940. mib[1] = KERN_PROC;
  1941. mib[2] = KERN_PROC_UMASK;
  1942. mib[3] = pid;
  1943. len = sizeof(*maskp);
  1944. error = sysctl(mib, nitems(mib), maskp, &len, NULL, 0);
  1945. if (error != 0 && errno != ESRCH && errno != EPERM)
  1946. warn("sysctl: kern.proc.umask: %d", pid);
  1947. return (error);
  1948. }
  1949. static int
  1950. procstat_getumask_core(struct procstat_core *core, unsigned short *maskp)
  1951. {
  1952. size_t len;
  1953. unsigned short *buf;
  1954. buf = procstat_core_get(core, PSC_TYPE_UMASK, NULL, &len);
  1955. if (buf == NULL)
  1956. return (-1);
  1957. if (len < sizeof(*maskp)) {
  1958. free(buf);
  1959. return (-1);
  1960. }
  1961. *maskp = *buf;
  1962. free(buf);
  1963. return (0);
  1964. }
  1965. int
  1966. procstat_getumask(struct procstat *procstat, struct kinfo_proc *kp,
  1967. unsigned short *maskp)
  1968. {
  1969. switch (procstat->type) {
  1970. case PROCSTAT_KVM:
  1971. return (procstat_getumask_kvm(procstat->kd, kp, maskp));
  1972. case PROCSTAT_SYSCTL:
  1973. return (procstat_getumask_sysctl(kp->ki_pid, maskp));
  1974. case PROCSTAT_CORE:
  1975. return (procstat_getumask_core(procstat->core, maskp));
  1976. default:
  1977. warnx("unknown access method: %d", procstat->type);
  1978. return (-1);
  1979. }
  1980. }
  1981. static int
  1982. procstat_getrlimit_kvm(kvm_t *kd, struct kinfo_proc *kp, int which,
  1983. struct rlimit* rlimit)
  1984. {
  1985. struct proc proc;
  1986. unsigned long offset;
  1987. assert(kd != NULL);
  1988. assert(kp != NULL);
  1989. assert(which >= 0 && which < RLIM_NLIMITS);
  1990. if (!kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc,
  1991. sizeof(proc))) {
  1992. warnx("can't read proc struct at %p for pid %d",
  1993. kp->ki_paddr, kp->ki_pid);
  1994. return (-1);
  1995. }
  1996. if (proc.p_limit == NULL)
  1997. return (-1);
  1998. offset = (unsigned long)proc.p_limit + sizeof(struct rlimit) * which;
  1999. if (!kvm_read_all(kd, offset, rlimit, sizeof(*rlimit))) {
  2000. warnx("can't read rlimit struct at %p for pid %d",
  2001. (void *)offset, kp->ki_pid);
  2002. return (-1);
  2003. }
  2004. return (0);
  2005. }
  2006. static int
  2007. procstat_getrlimit_sysctl(pid_t pid, int which, struct rlimit* rlimit)
  2008. {
  2009. int error, name[5];
  2010. size_t len;
  2011. name[0] = CTL_KERN;
  2012. name[1] = KERN_PROC;
  2013. name[2] = KERN_PROC_RLIMIT;
  2014. name[3] = pid;
  2015. name[4] = which;
  2016. len = sizeof(struct rlimit);
  2017. error = sysctl(name, nitems(name), rlimit, &len, NULL, 0);
  2018. if (error < 0 && errno != ESRCH) {
  2019. warn("sysctl: kern.proc.rlimit: %d", pid);
  2020. return (-1);
  2021. }
  2022. if (error < 0 || len != sizeof(struct rlimit))
  2023. return (-1);
  2024. return (0);
  2025. }
  2026. static int
  2027. procstat_getrlimit_core(struct procstat_core *core, int which,
  2028. struct rlimit* rlimit)
  2029. {
  2030. size_t len;
  2031. struct rlimit* rlimits;
  2032. if (which < 0 || which >= RLIM_NLIMITS) {
  2033. errno = EINVAL;
  2034. warn("getrlimit: which");
  2035. return (-1);
  2036. }
  2037. rlimits = procstat_core_get(core, PSC_TYPE_RLIMIT, NULL, &len);
  2038. if (rlimits == NULL)
  2039. return (-1);
  2040. if (len < sizeof(struct rlimit) * RLIM_NLIMITS) {
  2041. free(rlimits);
  2042. return (-1);
  2043. }
  2044. *rlimit = rlimits[which];
  2045. free(rlimits);
  2046. return (0);
  2047. }
  2048. int
  2049. procstat_getrlimit(struct procstat *procstat, struct kinfo_proc *kp, int which,
  2050. struct rlimit* rlimit)
  2051. {
  2052. switch (procstat->type) {
  2053. case PROCSTAT_KVM:
  2054. return (procstat_getrlimit_kvm(procstat->kd, kp, which,
  2055. rlimit));
  2056. case PROCSTAT_SYSCTL:
  2057. return (procstat_getrlimit_sysctl(kp->ki_pid, which, rlimit));
  2058. case PROCSTAT_CORE:
  2059. return (procstat_getrlimit_core(procstat->core, which, rlimit));
  2060. default:
  2061. warnx("unknown access method: %d", procstat->type);
  2062. return (-1);
  2063. }
  2064. }
  2065. static int
  2066. procstat_getpathname_sysctl(pid_t pid, char *pathname, size_t maxlen)
  2067. {
  2068. int error, name[4];
  2069. size_t len;
  2070. name[0] = CTL_KERN;
  2071. name[1] = KERN_PROC;
  2072. name[2] = KERN_PROC_PATHNAME;
  2073. name[3] = pid;
  2074. len = maxlen;
  2075. error = sysctl(name, nitems(name), pathname, &len, NULL, 0);
  2076. if (error != 0 && errno != ESRCH)
  2077. warn("sysctl: kern.proc.pathname: %d", pid);
  2078. if (len == 0)
  2079. pathname[0] = '\0';
  2080. return (error);
  2081. }
  2082. static int
  2083. procstat_getpathname_core(struct procstat_core *core, char *pathname,
  2084. size_t maxlen)
  2085. {
  2086. struct kinfo_file *files;
  2087. int cnt, i, result;
  2088. files = kinfo_getfile_core(core, &cnt);
  2089. if (files == NULL)
  2090. return (-1);
  2091. result = -1;
  2092. for (i = 0; i < cnt; i++) {
  2093. if (files[i].kf_fd != KF_FD_TYPE_TEXT)
  2094. continue;
  2095. strncpy(pathname, files[i].kf_path, maxlen);
  2096. result = 0;
  2097. break;
  2098. }
  2099. free(files);
  2100. return (result);
  2101. }
  2102. int
  2103. procstat_getpathname(struct procstat *procstat, struct kinfo_proc *kp,
  2104. char *pathname, size_t maxlen)
  2105. {
  2106. switch (procstat->type) {
  2107. case PROCSTAT_KVM:
  2108. /* XXX: Return empty string. */
  2109. if (maxlen > 0)
  2110. pathname[0] = '\0';
  2111. return (0);
  2112. case PROCSTAT_SYSCTL:
  2113. return (procstat_getpathname_sysctl(kp->ki_pid, pathname,
  2114. maxlen));
  2115. case PROCSTAT_CORE:
  2116. return (procstat_getpathname_core(procstat->core, pathname,
  2117. maxlen));
  2118. default:
  2119. warnx("unknown access method: %d", procstat->type);
  2120. return (-1);
  2121. }
  2122. }
  2123. static int
  2124. procstat_getosrel_kvm(kvm_t *kd, struct kinfo_proc *kp, int *osrelp)
  2125. {
  2126. struct proc proc;
  2127. assert(kd != NULL);
  2128. assert(kp != NULL);
  2129. if (!kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc,
  2130. sizeof(proc))) {
  2131. warnx("can't read proc struct at %p for pid %d",
  2132. kp->ki_paddr, kp->ki_pid);
  2133. return (-1);
  2134. }
  2135. *osrelp = proc.p_osrel;
  2136. return (0);
  2137. }
  2138. static int
  2139. procstat_getosrel_sysctl(pid_t pid, int *osrelp)
  2140. {
  2141. int error, name[4];
  2142. size_t len;
  2143. name[0] = CTL_KERN;
  2144. name[1] = KERN_PROC;
  2145. name[2] = KERN_PROC_OSREL;
  2146. name[3] = pid;
  2147. len = sizeof(*osrelp);
  2148. error = sysctl(name, nitems(name), osrelp, &len, NULL, 0);
  2149. if (error != 0 && errno != ESRCH)
  2150. warn("sysctl: kern.proc.osrel: %d", pid);
  2151. return (error);
  2152. }
  2153. static int
  2154. procstat_getosrel_core(struct procstat_core *core, int *osrelp)
  2155. {
  2156. size_t len;
  2157. int *buf;
  2158. buf = procstat_core_get(core, PSC_TYPE_OSREL, NULL, &len);
  2159. if (buf == NULL)
  2160. return (-1);
  2161. if (len < sizeof(*osrelp)) {
  2162. free(buf);
  2163. return (-1);
  2164. }
  2165. *osrelp = *buf;
  2166. free(buf);
  2167. return (0);
  2168. }
  2169. int
  2170. procstat_getosrel(struct procstat *procstat, struct kinfo_proc *kp, int *osrelp)
  2171. {
  2172. switch (procstat->type) {
  2173. case PROCSTAT_KVM:
  2174. return (procstat_getosrel_kvm(procstat->kd, kp, osrelp));
  2175. case PROCSTAT_SYSCTL:
  2176. return (procstat_getosrel_sysctl(kp->ki_pid, osrelp));
  2177. case PROCSTAT_CORE:
  2178. return (procstat_getosrel_core(procstat->core, osrelp));
  2179. default:
  2180. warnx("unknown access method: %d", procstat->type);
  2181. return (-1);
  2182. }
  2183. }
  2184. #define PROC_AUXV_MAX 256
  2185. #ifdef PS_ARCH_HAS_FREEBSD32
  2186. static const char *elf32_sv_names[] = {
  2187. "Linux ELF32",
  2188. "FreeBSD ELF32",
  2189. };
  2190. static int
  2191. is_elf32_sysctl(pid_t pid)
  2192. {
  2193. int error, name[4];
  2194. size_t len, i;
  2195. char sv_name[32];
  2196. name[0] = CTL_KERN;
  2197. name[1] = KERN_PROC;
  2198. name[2] = KERN_PROC_SV_NAME;
  2199. name[3] = pid;
  2200. len = sizeof(sv_name);
  2201. error = sysctl(name, nitems(name), sv_name, &len, NULL, 0);
  2202. if (error != 0 || len == 0)
  2203. return (0);
  2204. for (i = 0; i < sizeof(elf32_sv_names) / sizeof(*elf32_sv_names); i++) {
  2205. if (strncmp(sv_name, elf32_sv_names[i], sizeof(sv_name)) == 0)
  2206. return (1);
  2207. }
  2208. return (0);
  2209. }
  2210. static Elf_Auxinfo *
  2211. procstat_getauxv32_sysctl(pid_t pid, unsigned int *cntp)
  2212. {
  2213. Elf_Auxinfo *auxv;
  2214. Elf32_Auxinfo *auxv32;
  2215. size_t len;
  2216. unsigned int i, count;
  2217. int name[4];
  2218. name[0] = CTL_KERN;
  2219. name[1] = KERN_PROC;
  2220. name[2] = KERN_PROC_AUXV;
  2221. name[3] = pid;
  2222. len = PROC_AUXV_MAX * sizeof(Elf32_Auxinfo);
  2223. auxv = NULL;
  2224. auxv32 = malloc(len);
  2225. if (auxv32 == NULL) {
  2226. warn("malloc(%zu)", len);
  2227. goto out;
  2228. }
  2229. if (sysctl(name, nitems(name), auxv32, &len, NULL, 0) == -1) {
  2230. if (errno != ESRCH && errno != EPERM)
  2231. warn("sysctl: kern.proc.auxv: %d: %d", pid, errno);
  2232. goto out;
  2233. }
  2234. count = len / sizeof(Elf32_Auxinfo);
  2235. auxv = malloc(count * sizeof(Elf_Auxinfo));
  2236. if (auxv == NULL) {
  2237. warn("malloc(%zu)", count * sizeof(Elf_Auxinfo));
  2238. goto out;
  2239. }
  2240. for (i = 0; i < count; i++) {
  2241. /*
  2242. * XXX: We expect that values for a_type on a 32-bit platform
  2243. * are directly mapped to values on 64-bit one, which is not
  2244. * necessarily true.
  2245. */
  2246. auxv[i].a_type = auxv32[i].a_type;
  2247. /*
  2248. * Don't sign extend values. Existing entries are positive
  2249. * integers or pointers. Under freebsd32, programs typically
  2250. * have a full [0, 2^32) address space (perhaps minus the last
  2251. * page) and treating this as a signed integer would be
  2252. * confusing since these are not kernel pointers.
  2253. *
  2254. * XXX: A more complete translation would be ABI and
  2255. * type-aware.
  2256. */
  2257. auxv[i].a_un.a_val = (uint32_t)auxv32[i].a_un.a_val;
  2258. }
  2259. *cntp = count;
  2260. out:
  2261. free(auxv32);
  2262. return (auxv);
  2263. }
  2264. #endif /* PS_ARCH_HAS_FREEBSD32 */
  2265. static Elf_Auxinfo *
  2266. procstat_getauxv_sysctl(pid_t pid, unsigned int *cntp)
  2267. {
  2268. Elf_Auxinfo *auxv;
  2269. int name[4];
  2270. size_t len;
  2271. #ifdef PS_ARCH_HAS_FREEBSD32
  2272. if (is_elf32_sysctl(pid))
  2273. return (procstat_getauxv32_sysctl(pid, cntp));
  2274. #endif
  2275. name[0] = CTL_KERN;
  2276. name[1] = KERN_PROC;
  2277. name[2] = KERN_PROC_AUXV;
  2278. name[3] = pid;
  2279. len = PROC_AUXV_MAX * sizeof(Elf_Auxinfo);
  2280. auxv = malloc(len);
  2281. if (auxv == NULL) {
  2282. warn("malloc(%zu)", len);
  2283. return (NULL);
  2284. }
  2285. if (sysctl(name, nitems(name), auxv, &len, NULL, 0) == -1) {
  2286. if (errno != ESRCH && errno != EPERM)
  2287. warn("sysctl: kern.proc.auxv: %d: %d", pid, errno);
  2288. free(auxv);
  2289. return (NULL);
  2290. }
  2291. *cntp = len / sizeof(Elf_Auxinfo);
  2292. return (auxv);
  2293. }
  2294. static Elf_Auxinfo *
  2295. procstat_getauxv_core(struct procstat_core *core, unsigned int *cntp)
  2296. {
  2297. Elf_Auxinfo *auxv;
  2298. size_t len;
  2299. auxv = procstat_core_get(core, PSC_TYPE_AUXV, NULL, &len);
  2300. if (auxv == NULL)
  2301. return (NULL);
  2302. *cntp = len / sizeof(Elf_Auxinfo);
  2303. return (auxv);
  2304. }
  2305. Elf_Auxinfo *
  2306. procstat_getauxv(struct procstat *procstat, struct kinfo_proc *kp,
  2307. unsigned int *cntp)
  2308. {
  2309. switch (procstat->type) {
  2310. case PROCSTAT_KVM:
  2311. warnx("kvm method is not supported");
  2312. return (NULL);
  2313. case PROCSTAT_SYSCTL:
  2314. return (procstat_getauxv_sysctl(kp->ki_pid, cntp));
  2315. case PROCSTAT_CORE:
  2316. return (procstat_getauxv_core(procstat->core, cntp));
  2317. default:
  2318. warnx("unknown access method: %d", procstat->type);
  2319. return (NULL);
  2320. }
  2321. }
  2322. void
  2323. procstat_freeauxv(struct procstat *procstat __unused, Elf_Auxinfo *auxv)
  2324. {
  2325. free(auxv);
  2326. }
  2327. static struct ptrace_lwpinfo *
  2328. procstat_getptlwpinfo_core(struct procstat_core *core, unsigned int *cntp)
  2329. {
  2330. void *buf;
  2331. struct ptrace_lwpinfo *pl;
  2332. unsigned int cnt;
  2333. size_t len;
  2334. cnt = procstat_core_note_count(core, PSC_TYPE_PTLWPINFO);
  2335. if (cnt == 0)
  2336. return (NULL);
  2337. len = cnt * sizeof(*pl);
  2338. buf = calloc(1, len);
  2339. pl = procstat_core_get(core, PSC_TYPE_PTLWPINFO, buf, &len);
  2340. if (pl == NULL) {
  2341. free(buf);
  2342. return (NULL);
  2343. }
  2344. *cntp = len / sizeof(*pl);
  2345. return (pl);
  2346. }
  2347. struct ptrace_lwpinfo *
  2348. procstat_getptlwpinfo(struct procstat *procstat, unsigned int *cntp)
  2349. {
  2350. switch (procstat->type) {
  2351. case PROCSTAT_KVM:
  2352. warnx("kvm method is not supported");
  2353. return (NULL);
  2354. case PROCSTAT_SYSCTL:
  2355. warnx("sysctl method is not supported");
  2356. return (NULL);
  2357. case PROCSTAT_CORE:
  2358. return (procstat_getptlwpinfo_core(procstat->core, cntp));
  2359. default:
  2360. warnx("unknown access method: %d", procstat->type);
  2361. return (NULL);
  2362. }
  2363. }
  2364. void
  2365. procstat_freeptlwpinfo(struct procstat *procstat __unused,
  2366. struct ptrace_lwpinfo *pl)
  2367. {
  2368. free(pl);
  2369. }
  2370. static struct kinfo_kstack *
  2371. procstat_getkstack_sysctl(pid_t pid, int *cntp)
  2372. {
  2373. struct kinfo_kstack *kkstp;
  2374. int error, name[4];
  2375. size_t len;
  2376. name[0] = CTL_KERN;
  2377. name[1] = KERN_PROC;
  2378. name[2] = KERN_PROC_KSTACK;
  2379. name[3] = pid;
  2380. len = 0;
  2381. error = sysctl(name, nitems(name), NULL, &len, NULL, 0);
  2382. if (error < 0 && errno != ESRCH && errno != EPERM && errno != ENOENT) {
  2383. warn("sysctl: kern.proc.kstack: %d", pid);
  2384. return (NULL);
  2385. }
  2386. if (error == -1 && errno == ENOENT) {
  2387. warnx("sysctl: kern.proc.kstack unavailable"
  2388. " (options DDB or options STACK required in kernel)");
  2389. return (NULL);
  2390. }
  2391. if (error == -1)
  2392. return (NULL);
  2393. kkstp = malloc(len);
  2394. if (kkstp == NULL) {
  2395. warn("malloc(%zu)", len);
  2396. return (NULL);
  2397. }
  2398. if (sysctl(name, nitems(name), kkstp, &len, NULL, 0) == -1 &&
  2399. errno != ENOMEM) {
  2400. warn("sysctl: kern.proc.pid: %d", pid);
  2401. free(kkstp);
  2402. return (NULL);
  2403. }
  2404. *cntp = len / sizeof(*kkstp);
  2405. return (kkstp);
  2406. }
  2407. struct kinfo_kstack *
  2408. procstat_getkstack(struct procstat *procstat, struct kinfo_proc *kp,
  2409. unsigned int *cntp)
  2410. {
  2411. switch (procstat->type) {
  2412. case PROCSTAT_KVM:
  2413. warnx("kvm method is not supported");
  2414. return (NULL);
  2415. case PROCSTAT_SYSCTL:
  2416. return (procstat_getkstack_sysctl(kp->ki_pid, cntp));
  2417. case PROCSTAT_CORE:
  2418. warnx("core method is not supported");
  2419. return (NULL);
  2420. default:
  2421. warnx("unknown access method: %d", procstat->type);
  2422. return (NULL);
  2423. }
  2424. }
  2425. void
  2426. procstat_freekstack(struct procstat *procstat __unused,
  2427. struct kinfo_kstack *kkstp)
  2428. {
  2429. free(kkstp);
  2430. }
  2431. static struct advlock_list *
  2432. procstat_getadvlock_sysctl(struct procstat *procstat __unused)
  2433. {
  2434. struct advlock_list *res;
  2435. struct advlock *a;
  2436. void *buf;
  2437. char *c;
  2438. struct kinfo_lockf *kl;
  2439. size_t buf_len;
  2440. int error;
  2441. static const int kl_name[] = { CTL_KERN, KERN_LOCKF };
  2442. res = malloc(sizeof(*res));
  2443. if (res == NULL)
  2444. return (NULL);
  2445. STAILQ_INIT(res);
  2446. buf = NULL;
  2447. buf_len = 0;
  2448. error = sysctl(kl_name, nitems(kl_name), NULL, &buf_len, NULL, 0);
  2449. if (error != 0) {
  2450. warn("sysctl KERN_LOCKF size");
  2451. goto fail;
  2452. }
  2453. buf_len *= 2;
  2454. buf = malloc(buf_len);
  2455. if (buf == NULL) {
  2456. warn("malloc");
  2457. goto fail;
  2458. }
  2459. error = sysctl(kl_name, nitems(kl_name), buf, &buf_len, NULL, 0);
  2460. if (error != 0) {
  2461. warn("sysctl KERN_LOCKF data");
  2462. goto fail;
  2463. }
  2464. for (c = buf; (char *)c < (char *)buf + buf_len;
  2465. c += kl->kl_structsize) {
  2466. kl = (struct kinfo_lockf *)(void *)c;
  2467. if (sizeof(*kl) < (size_t)kl->kl_structsize) {
  2468. warn("ABI broken");
  2469. goto fail;
  2470. }
  2471. a = malloc(sizeof(*a));
  2472. if (a == NULL) {
  2473. warn("malloc advlock");
  2474. goto fail;
  2475. }
  2476. switch (kl->kl_rw) {
  2477. case KLOCKF_RW_READ:
  2478. a->rw = PS_ADVLOCK_RO;
  2479. break;
  2480. case KLOCKF_RW_WRITE:
  2481. a->rw = PS_ADVLOCK_RW;
  2482. break;
  2483. default:
  2484. warn("ABI broken");
  2485. free(a);
  2486. goto fail;
  2487. }
  2488. switch (kl->kl_type) {
  2489. case KLOCKF_TYPE_FLOCK:
  2490. a->type = PS_ADVLOCK_TYPE_FLOCK;
  2491. break;
  2492. case KLOCKF_TYPE_PID:
  2493. a->type = PS_ADVLOCK_TYPE_PID;
  2494. break;
  2495. case KLOCKF_TYPE_REMOTE:
  2496. a->type = PS_ADVLOCK_TYPE_REMOTE;
  2497. break;
  2498. default:
  2499. warn("ABI broken");
  2500. free(a);
  2501. goto fail;
  2502. }
  2503. a->pid = kl->kl_pid;
  2504. a->sysid = kl->kl_sysid;
  2505. a->file_fsid = kl->kl_file_fsid;
  2506. a->file_rdev = kl->kl_file_rdev;
  2507. a->file_fileid = kl->kl_file_fileid;
  2508. a->start = kl->kl_start;
  2509. a->len = kl->kl_len;
  2510. if (kl->kl_path[0] != '\0') {
  2511. a->path = strdup(kl->kl_path);
  2512. if (a->path == NULL) {
  2513. warn("malloc");
  2514. free(a);
  2515. goto fail;
  2516. }
  2517. } else
  2518. a->path = NULL;
  2519. STAILQ_INSERT_TAIL(res, a, next);
  2520. }
  2521. free(buf);
  2522. return (res);
  2523. fail:
  2524. free(buf);
  2525. procstat_freeadvlock(procstat, res);
  2526. return (NULL);
  2527. }
  2528. struct advlock_list *
  2529. procstat_getadvlock(struct procstat *procstat)
  2530. {
  2531. switch (procstat->type) {
  2532. case PROCSTAT_KVM:
  2533. warnx("kvm method is not supported");
  2534. return (NULL);
  2535. case PROCSTAT_SYSCTL:
  2536. return (procstat_getadvlock_sysctl(procstat));
  2537. case PROCSTAT_CORE:
  2538. warnx("core method is not supported");
  2539. return (NULL);
  2540. default:
  2541. warnx("unknown access method: %d", procstat->type);
  2542. return (NULL);
  2543. }
  2544. }
  2545. void
  2546. procstat_freeadvlock(struct procstat *procstat __unused,
  2547. struct advlock_list *lst)
  2548. {
  2549. struct advlock *a, *a1;
  2550. STAILQ_FOREACH_SAFE(a, lst, next, a1) {
  2551. free(__DECONST(char *, a->path));
  2552. free(a);
  2553. }
  2554. free(lst);
  2555. }