devproc.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "../port/error.h"
  7. #include "ureg.h"
  8. enum
  9. {
  10. Qdir,
  11. Qargs,
  12. Qctl,
  13. Qfd,
  14. Qfpregs,
  15. Qkregs,
  16. Qmem,
  17. Qnote,
  18. Qnoteid,
  19. Qnotepg,
  20. Qns,
  21. Qproc,
  22. Qregs,
  23. Qsegment,
  24. Qstatus,
  25. Qtext,
  26. Qwait,
  27. Qprofile,
  28. };
  29. enum
  30. {
  31. CMclose,
  32. CMclosefiles,
  33. CMfixedpri,
  34. CMhang,
  35. CMkill,
  36. CMnohang,
  37. CMnoswap,
  38. CMpri,
  39. CMprivate,
  40. CMprofile,
  41. CMstart,
  42. CMstartstop,
  43. CMstop,
  44. CMwaitstop,
  45. CMwired,
  46. };
  47. #define STATSIZE (2*KNAMELEN+12+9*12)
  48. /*
  49. * Status, fd, and ns are left fully readable (0444) because of their use in debugging,
  50. * particularly on shared servers.
  51. * Arguably, ns and fd shouldn't be readable; if you'd prefer, change them to 0000
  52. */
  53. Dirtab procdir[] =
  54. {
  55. "args", {Qargs}, 0, 0660,
  56. "ctl", {Qctl}, 0, 0000,
  57. "fd", {Qfd}, 0, 0444,
  58. "fpregs", {Qfpregs}, sizeof(FPsave), 0000,
  59. "kregs", {Qkregs}, sizeof(Ureg), 0400,
  60. "mem", {Qmem}, 0, 0000,
  61. "note", {Qnote}, 0, 0000,
  62. "noteid", {Qnoteid}, 0, 0664,
  63. "notepg", {Qnotepg}, 0, 0000,
  64. "ns", {Qns}, 0, 0444,
  65. "proc", {Qproc}, 0, 0400,
  66. "regs", {Qregs}, sizeof(Ureg), 0000,
  67. "segment", {Qsegment}, 0, 0444,
  68. "status", {Qstatus}, STATSIZE, 0444,
  69. "text", {Qtext}, 0, 0000,
  70. "wait", {Qwait}, 0, 0400,
  71. "profile", {Qprofile}, 0, 0400,
  72. };
  73. static
  74. Cmdtab proccmd[] = {
  75. CMclose, "close", 2,
  76. CMclosefiles, "closefiles", 1,
  77. CMfixedpri, "fixedpri", 2,
  78. CMhang, "hang", 1,
  79. CMnohang, "nohang", 1,
  80. CMnoswap, "noswap", 1,
  81. CMkill, "kill", 1,
  82. CMpri, "pri", 2,
  83. CMprivate, "private", 1,
  84. CMprofile, "profile", 1,
  85. CMstart, "start", 1,
  86. CMstartstop, "startstop", 1,
  87. CMstop, "stop", 1,
  88. CMwaitstop, "waitstop", 1,
  89. CMwired, "wired", 2,
  90. };
  91. /* Segment type from portdat.h */
  92. static char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", };
  93. /*
  94. * Qids are, in path:
  95. * 4 bits of file type (qids above)
  96. * 23 bits of process slot number + 1
  97. * in vers,
  98. * 32 bits of pid, for consistency checking
  99. * If notepg, c->pgrpid.path is pgrp slot, .vers is noteid.
  100. */
  101. #define QSHIFT 5 /* location in qid of proc slot # */
  102. #define QID(q) ((((ulong)(q).path)&0x0000001F)>>0)
  103. #define SLOT(q) (((((ulong)(q).path)&0x07FFFFFE0)>>QSHIFT)-1)
  104. #define PID(q) ((q).vers)
  105. #define NOTEID(q) ((q).vers)
  106. void procctlreq(Proc*, char*, int);
  107. int procctlmemio(Proc*, ulong, int, void*, int);
  108. Chan* proctext(Chan*, Proc*);
  109. Segment* txt2data(Proc*, Segment*);
  110. int procstopped(void*);
  111. void mntscan(Mntwalk*, Proc*);
  112. static int
  113. procgen(Chan *c, char *name, Dirtab *tab, int, int s, Dir *dp)
  114. {
  115. Qid qid;
  116. Proc *p;
  117. char *ename;
  118. Segment *q;
  119. ulong pid, path, perm, len;
  120. if(s == DEVDOTDOT){
  121. mkqid(&qid, Qdir, 0, QTDIR);
  122. devdir(c, qid, "#p", 0, eve, 0555, dp);
  123. return 1;
  124. }
  125. if(c->qid.path == Qdir){
  126. if(name != nil){
  127. /* ignore s and use name to find pid */
  128. pid = strtol(name, &ename, 10);
  129. if(pid==0 || ename[0]!='\0')
  130. return -1;
  131. s = procindex(pid);
  132. if(s < 0)
  133. return -1;
  134. }else
  135. if(s >= conf.nproc)
  136. return -1;
  137. p = proctab(s);
  138. pid = p->pid;
  139. if(pid == 0)
  140. return 0;
  141. sprint(up->genbuf, "%lud", pid);
  142. /*
  143. * String comparison is done in devwalk so name must match its formatted pid
  144. */
  145. if(name != nil && strcmp(name, up->genbuf) != 0)
  146. return -1;
  147. mkqid(&qid, (s+1)<<QSHIFT, pid, QTDIR);
  148. devdir(c, qid, up->genbuf, 0, p->user, DMDIR|0555, dp);
  149. return 1;
  150. }
  151. if(s >= nelem(procdir))
  152. return -1;
  153. if(tab)
  154. panic("procgen");
  155. tab = &procdir[s];
  156. path = c->qid.path&~(((1<<QSHIFT)-1)); /* slot component */
  157. p = proctab(SLOT(c->qid));
  158. perm = tab->perm;
  159. if(perm == 0)
  160. perm = p->procmode;
  161. else /* just copy read bits */
  162. perm |= p->procmode & 0444;
  163. len = tab->length;
  164. switch(QID(c->qid)) {
  165. case Qwait:
  166. len = p->nwait; /* incorrect size, but >0 means there's something to read */
  167. break;
  168. case Qprofile:
  169. q = p->seg[TSEG];
  170. if(q && q->profile) {
  171. len = (q->top-q->base)>>LRESPROF;
  172. len *= sizeof(*q->profile);
  173. }
  174. break;
  175. }
  176. mkqid(&qid, path|tab->qid.path, c->qid.vers, QTFILE);
  177. devdir(c, qid, tab->name, len, p->user, perm, dp);
  178. return 1;
  179. }
  180. static void
  181. procinit(void)
  182. {
  183. if(conf.nproc >= (1<<(16-QSHIFT))-1)
  184. print("warning: too many procs for devproc\n");
  185. }
  186. static Chan*
  187. procattach(char *spec)
  188. {
  189. return devattach('p', spec);
  190. }
  191. static Walkqid*
  192. procwalk(Chan *c, Chan *nc, char **name, int nname)
  193. {
  194. return devwalk(c, nc, name, nname, 0, 0, procgen);
  195. }
  196. static int
  197. procstat(Chan *c, uchar *db, int n)
  198. {
  199. return devstat(c, db, n, 0, 0, procgen);
  200. }
  201. /*
  202. * none can't read or write state on other
  203. * processes. This is to contain access of
  204. * servers running as none should they be
  205. * subverted by, for example, a stack attack.
  206. */
  207. static void
  208. nonone(Proc *p)
  209. {
  210. if(p == up)
  211. return;
  212. if(strcmp(up->user, "none") != 0)
  213. return;
  214. if(iseve())
  215. return;
  216. error(Eperm);
  217. }
  218. static Chan*
  219. procopen(Chan *c, int omode)
  220. {
  221. Proc *p;
  222. Pgrp *pg;
  223. Chan *tc;
  224. int pid;
  225. if(c->qid.type & QTDIR)
  226. return devopen(c, omode, 0, 0, procgen);
  227. p = proctab(SLOT(c->qid));
  228. qlock(&p->debug);
  229. if(waserror()){
  230. qunlock(&p->debug);
  231. nexterror();
  232. }
  233. pid = PID(c->qid);
  234. if(p->pid != pid)
  235. error(Eprocdied);
  236. omode = openmode(omode);
  237. switch(QID(c->qid)){
  238. case Qtext:
  239. if(omode != OREAD)
  240. error(Eperm);
  241. tc = proctext(c, p);
  242. tc->offset = 0;
  243. qunlock(&p->debug);
  244. poperror();
  245. return tc;
  246. case Qproc:
  247. case Qkregs:
  248. case Qsegment:
  249. case Qprofile:
  250. case Qfd:
  251. if(omode != OREAD)
  252. error(Eperm);
  253. break;
  254. case Qmem:
  255. case Qnote:
  256. case Qctl:
  257. if(p->privatemem)
  258. error(Eperm);
  259. /* fall through */
  260. case Qargs:
  261. case Qnoteid:
  262. case Qstatus:
  263. case Qwait:
  264. case Qregs:
  265. case Qfpregs:
  266. nonone(p);
  267. break;
  268. case Qns:
  269. if(omode != OREAD)
  270. error(Eperm);
  271. c->aux = malloc(sizeof(Mntwalk));
  272. break;
  273. case Qnotepg:
  274. nonone(p);
  275. pg = p->pgrp;
  276. if(pg == nil)
  277. error(Eprocdied);
  278. if(omode!=OWRITE || pg->pgrpid == 1)
  279. error(Eperm);
  280. c->pgrpid.path = pg->pgrpid+1;
  281. c->pgrpid.vers = p->noteid;
  282. break;
  283. default:
  284. pprint("procopen %lux\n", c->qid);
  285. error(Egreg);
  286. }
  287. /* Affix pid to qid */
  288. if(p->state != Dead)
  289. c->qid.vers = p->pid;
  290. /* make sure the process slot didn't get reallocated while we were playing */
  291. coherence();
  292. if(p->pid != pid)
  293. error(Eprocdied);
  294. tc = devopen(c, omode, 0, 0, procgen);
  295. qunlock(&p->debug);
  296. poperror();
  297. return tc;
  298. }
  299. static int
  300. procwstat(Chan *c, uchar *db, int n)
  301. {
  302. Proc *p;
  303. Dir *d;
  304. if(c->qid.type&QTDIR)
  305. error(Eperm);
  306. p = proctab(SLOT(c->qid));
  307. nonone(p);
  308. d = nil;
  309. if(waserror()){
  310. free(d);
  311. qunlock(&p->debug);
  312. nexterror();
  313. }
  314. qlock(&p->debug);
  315. if(p->pid != PID(c->qid))
  316. error(Eprocdied);
  317. if(strcmp(up->user, p->user) != 0 && strcmp(up->user, eve) != 0)
  318. error(Eperm);
  319. d = smalloc(sizeof(Dir)+n);
  320. n = convM2D(db, n, &d[0], (char*)&d[1]);
  321. if(n == 0)
  322. error(Eshortstat);
  323. if(!emptystr(d->uid) && strcmp(d->uid, p->user) != 0){
  324. if(strcmp(up->user, eve) != 0)
  325. error(Eperm);
  326. else
  327. kstrdup(&p->user, d->uid);
  328. }
  329. if(d->mode != ~0UL)
  330. p->procmode = d->mode&0777;
  331. poperror();
  332. free(d);
  333. qunlock(&p->debug);
  334. return n;
  335. }
  336. static long
  337. procoffset(long offset, char *va, int *np)
  338. {
  339. if(offset > 0) {
  340. offset -= *np;
  341. if(offset < 0) {
  342. memmove(va, va+*np+offset, -offset);
  343. *np = -offset;
  344. }
  345. else
  346. *np = 0;
  347. }
  348. return offset;
  349. }
  350. static int
  351. procqidwidth(Chan *c)
  352. {
  353. char buf[32];
  354. return sprint(buf, "%lud", c->qid.vers);
  355. }
  356. int
  357. procfdprint(Chan *c, int fd, int w, char *s, int ns)
  358. {
  359. int n;
  360. if(w == 0)
  361. w = procqidwidth(c);
  362. n = snprint(s, ns, "%3d %.2s %C %4ld (%.16llux %*lud %.2ux) %5ld %8lld %s\n",
  363. fd,
  364. &"r w rw"[(c->mode&3)<<1],
  365. devtab[c->type]->dc, c->dev,
  366. c->qid.path, w, c->qid.vers, c->qid.type,
  367. c->iounit, c->offset, c->name->s);
  368. return n;
  369. }
  370. static int
  371. procfds(Proc *p, char *va, int count, long offset)
  372. {
  373. Fgrp *f;
  374. Chan *c;
  375. char buf[256];
  376. int n, i, w, ww;
  377. char *a;
  378. /* print to buf to avoid holding fgrp lock while writing to user space */
  379. if(count > sizeof buf)
  380. count = sizeof buf;
  381. a = buf;
  382. qlock(&p->debug);
  383. f = p->fgrp;
  384. if(f == nil){
  385. qunlock(&p->debug);
  386. return 0;
  387. }
  388. lock(f);
  389. if(waserror()){
  390. unlock(f);
  391. qunlock(&p->debug);
  392. nexterror();
  393. }
  394. n = readstr(0, a, count, p->dot->name->s);
  395. n += snprint(a+n, count-n, "\n");
  396. offset = procoffset(offset, a, &n);
  397. /* compute width of qid.path */
  398. w = 0;
  399. for(i = 0; i <= f->maxfd; i++) {
  400. c = f->fd[i];
  401. if(c == nil)
  402. continue;
  403. ww = procqidwidth(c);
  404. if(ww > w)
  405. w = ww;
  406. }
  407. for(i = 0; i <= f->maxfd; i++) {
  408. c = f->fd[i];
  409. if(c == nil)
  410. continue;
  411. n += procfdprint(c, i, w, a+n, count-n);
  412. offset = procoffset(offset, a, &n);
  413. }
  414. unlock(f);
  415. qunlock(&p->debug);
  416. poperror();
  417. /* copy result to user space, now that locks are released */
  418. memmove(va, buf, n);
  419. return n;
  420. }
  421. static void
  422. procclose(Chan * c)
  423. {
  424. if(QID(c->qid) == Qns && c->aux != 0)
  425. free(c->aux);
  426. }
  427. static void
  428. int2flag(int flag, char *s)
  429. {
  430. if(flag == 0){
  431. *s = '\0';
  432. return;
  433. }
  434. *s++ = '-';
  435. if(flag & MAFTER)
  436. *s++ = 'a';
  437. if(flag & MBEFORE)
  438. *s++ = 'b';
  439. if(flag & MCREATE)
  440. *s++ = 'c';
  441. if(flag & MCACHE)
  442. *s++ = 'C';
  443. *s = '\0';
  444. }
  445. static int
  446. procargs(Proc *p, char *buf, int nbuf)
  447. {
  448. int j, k, m;
  449. char *a;
  450. int n;
  451. a = p->args;
  452. if(p->setargs){
  453. snprint(buf, nbuf, "%s [%s]", p->text, p->args);
  454. return strlen(buf);
  455. }
  456. n = p->nargs;
  457. for(j = 0; j < nbuf - 1; j += m){
  458. if(n <= 0)
  459. break;
  460. if(j != 0)
  461. buf[j++] = ' ';
  462. m = snprint(buf+j, nbuf-j, "%q", a);
  463. k = strlen(a) + 1;
  464. a += k;
  465. n -= k;
  466. }
  467. return j;
  468. }
  469. static long
  470. procread(Chan *c, void *va, long n, vlong off)
  471. {
  472. int m;
  473. long l;
  474. Proc *p;
  475. Waitq *wq;
  476. Ureg kur;
  477. uchar *rptr;
  478. Mntwalk *mw;
  479. Segment *sg, *s;
  480. char *a = va, *sps;
  481. int i, j, rsize, pid;
  482. char statbuf[NSEG*32], *srv, flag[10];
  483. ulong offset = off;
  484. if(c->qid.type & QTDIR)
  485. return devdirread(c, a, n, 0, 0, procgen);
  486. p = proctab(SLOT(c->qid));
  487. if(p->pid != PID(c->qid))
  488. error(Eprocdied);
  489. switch(QID(c->qid)){
  490. case Qargs:
  491. qlock(&p->debug);
  492. j = procargs(p, p->genbuf, sizeof p->genbuf);
  493. qunlock(&p->debug);
  494. if(offset >= j)
  495. return 0;
  496. if(offset+n > j)
  497. n = j-offset;
  498. memmove(a, &p->genbuf[offset], n);
  499. return n;
  500. case Qmem:
  501. if(offset < KZERO
  502. || (offset >= USTKTOP-USTKSIZE && offset < USTKTOP))
  503. return procctlmemio(p, offset, n, va, 1);
  504. if(!iseve())
  505. error(Eperm);
  506. /* validate kernel addresses */
  507. if(offset < (ulong)end) {
  508. if(offset+n > (ulong)end)
  509. n = (ulong)end - offset;
  510. memmove(a, (char*)offset, n);
  511. return n;
  512. }
  513. /* conf.base* and conf.npage* are set by xinit to refer to kernel allocation, not user pages */
  514. if(offset >= conf.base0 && offset < conf.npage0){
  515. if(offset+n > conf.npage0)
  516. n = conf.npage0 - offset;
  517. memmove(a, (char*)offset, n);
  518. return n;
  519. }
  520. if(offset >= conf.base1 && offset < conf.npage1){
  521. if(offset+n > conf.npage1)
  522. n = conf.npage1 - offset;
  523. memmove(a, (char*)offset, n);
  524. return n;
  525. }
  526. error(Ebadarg);
  527. case Qprofile:
  528. s = p->seg[TSEG];
  529. if(s == 0 || s->profile == 0)
  530. error("profile is off");
  531. i = (s->top-s->base)>>LRESPROF;
  532. i *= sizeof(*s->profile);
  533. if(offset >= i)
  534. return 0;
  535. if(offset+n > i)
  536. n = i - offset;
  537. memmove(a, ((char*)s->profile)+offset, n);
  538. return n;
  539. case Qnote:
  540. qlock(&p->debug);
  541. if(waserror()){
  542. qunlock(&p->debug);
  543. nexterror();
  544. }
  545. if(p->pid != PID(c->qid))
  546. error(Eprocdied);
  547. if(n < 1) /* must accept at least the '\0' */
  548. error(Etoosmall);
  549. if(p->nnote == 0)
  550. n = 0;
  551. else {
  552. m = strlen(p->note[0].msg) + 1;
  553. if(m > n)
  554. m = n;
  555. memmove(va, p->note[0].msg, m);
  556. ((char*)va)[m-1] = '\0';
  557. p->nnote--;
  558. memmove(p->note, p->note+1, p->nnote*sizeof(Note));
  559. n = m;
  560. }
  561. if(p->nnote == 0)
  562. p->notepending = 0;
  563. poperror();
  564. qunlock(&p->debug);
  565. return n;
  566. case Qproc:
  567. if(offset >= sizeof(Proc))
  568. return 0;
  569. if(offset+n > sizeof(Proc))
  570. n = sizeof(Proc) - offset;
  571. memmove(a, ((char*)p)+offset, n);
  572. return n;
  573. case Qregs:
  574. rptr = (uchar*)p->dbgreg;
  575. rsize = sizeof(Ureg);
  576. goto regread;
  577. case Qkregs:
  578. memset(&kur, 0, sizeof(Ureg));
  579. setkernur(&kur, p);
  580. rptr = (uchar*)&kur;
  581. rsize = sizeof(Ureg);
  582. goto regread;
  583. case Qfpregs:
  584. rptr = (uchar*)&p->fpsave;
  585. rsize = sizeof(FPsave);
  586. regread:
  587. if(rptr == 0)
  588. error(Enoreg);
  589. if(offset >= rsize)
  590. return 0;
  591. if(offset+n > rsize)
  592. n = rsize - offset;
  593. memmove(a, rptr+offset, n);
  594. return n;
  595. case Qstatus:
  596. if(offset >= STATSIZE)
  597. return 0;
  598. if(offset+n > STATSIZE)
  599. n = STATSIZE - offset;
  600. sps = p->psstate;
  601. if(sps == 0)
  602. sps = statename[p->state];
  603. memset(statbuf, ' ', sizeof statbuf);
  604. memmove(statbuf+0*KNAMELEN, p->text, strlen(p->text));
  605. memmove(statbuf+1*KNAMELEN, p->user, strlen(p->user));
  606. memmove(statbuf+2*KNAMELEN, sps, strlen(sps));
  607. j = 2*KNAMELEN + 12;
  608. for(i = 0; i < 6; i++) {
  609. l = p->time[i];
  610. if(i == TReal)
  611. l = MACHP(0)->ticks - l;
  612. l = TK2MS(l);
  613. readnum(0, statbuf+j+NUMSIZE*i, NUMSIZE, l, NUMSIZE);
  614. }
  615. /* ignore stack, which is mostly non-existent */
  616. l = 0;
  617. for(i=1; i<NSEG; i++){
  618. s = p->seg[i];
  619. if(s)
  620. l += s->top - s->base;
  621. }
  622. readnum(0, statbuf+j+NUMSIZE*6, NUMSIZE, l>>10, NUMSIZE);
  623. readnum(0, statbuf+j+NUMSIZE*7, NUMSIZE, p->basepri, NUMSIZE);
  624. readnum(0, statbuf+j+NUMSIZE*8, NUMSIZE, p->priority, NUMSIZE);
  625. memmove(a, statbuf+offset, n);
  626. return n;
  627. case Qsegment:
  628. j = 0;
  629. for(i = 0; i < NSEG; i++) {
  630. sg = p->seg[i];
  631. if(sg == 0)
  632. continue;
  633. j += sprint(statbuf+j, "%-6s %c%c %.8lux %.8lux %4ld\n",
  634. sname[sg->type&SG_TYPE],
  635. sg->type&SG_RONLY ? 'R' : ' ',
  636. sg->profile ? 'P' : ' ',
  637. sg->base, sg->top, sg->ref);
  638. }
  639. if(offset >= j)
  640. return 0;
  641. if(offset+n > j)
  642. n = j-offset;
  643. if(n == 0 && offset == 0)
  644. exhausted("segments");
  645. memmove(a, &statbuf[offset], n);
  646. return n;
  647. case Qwait:
  648. if(!canqlock(&p->qwaitr))
  649. error(Einuse);
  650. if(waserror()) {
  651. qunlock(&p->qwaitr);
  652. nexterror();
  653. }
  654. lock(&p->exl);
  655. if(up == p && p->nchild == 0 && p->waitq == 0) {
  656. unlock(&p->exl);
  657. error(Enochild);
  658. }
  659. pid = p->pid;
  660. while(p->waitq == 0) {
  661. unlock(&p->exl);
  662. sleep(&p->waitr, haswaitq, p);
  663. if(p->pid != pid)
  664. error(Eprocdied);
  665. lock(&p->exl);
  666. }
  667. wq = p->waitq;
  668. p->waitq = wq->next;
  669. p->nwait--;
  670. unlock(&p->exl);
  671. qunlock(&p->qwaitr);
  672. poperror();
  673. n = snprint(a, n, "%d %lud %lud %lud %q",
  674. wq->w.pid,
  675. wq->w.time[TUser], wq->w.time[TSys], wq->w.time[TReal],
  676. wq->w.msg);
  677. free(wq);
  678. return n;
  679. case Qns:
  680. qlock(&p->debug);
  681. if(waserror()){
  682. qunlock(&p->debug);
  683. nexterror();
  684. }
  685. if(p->pgrp == nil || p->pid != PID(c->qid))
  686. error(Eprocdied);
  687. mw = c->aux;
  688. if(mw->cddone){
  689. qunlock(&p->debug);
  690. poperror();
  691. return 0;
  692. }
  693. mntscan(mw, p);
  694. if(mw->mh == 0){
  695. mw->cddone = 1;
  696. i = snprint(a, n, "cd %s\n", p->dot->name->s);
  697. qunlock(&p->debug);
  698. poperror();
  699. return i;
  700. }
  701. int2flag(mw->cm->mflag, flag);
  702. if(strcmp(mw->cm->to->name->s, "#M") == 0){
  703. srv = srvname(mw->cm->to->mchan);
  704. i = snprint(a, n, "mount %s %s %s %s\n", flag,
  705. srv==nil? mw->cm->to->mchan->name->s : srv,
  706. mw->mh->from->name->s, mw->cm->spec? mw->cm->spec : "");
  707. free(srv);
  708. }else
  709. i = snprint(a, n, "bind %s %s %s\n", flag,
  710. mw->cm->to->name->s, mw->mh->from->name->s);
  711. qunlock(&p->debug);
  712. poperror();
  713. return i;
  714. case Qnoteid:
  715. return readnum(offset, va, n, p->noteid, NUMSIZE);
  716. case Qfd:
  717. return procfds(p, va, n, offset);
  718. }
  719. error(Egreg);
  720. return 0; /* not reached */
  721. }
  722. void
  723. mntscan(Mntwalk *mw, Proc *p)
  724. {
  725. Pgrp *pg;
  726. Mount *t;
  727. Mhead *f;
  728. int nxt, i;
  729. ulong last, bestmid;
  730. pg = p->pgrp;
  731. rlock(&pg->ns);
  732. nxt = 0;
  733. bestmid = ~0;
  734. last = 0;
  735. if(mw->mh)
  736. last = mw->cm->mountid;
  737. for(i = 0; i < MNTHASH; i++) {
  738. for(f = pg->mnthash[i]; f; f = f->hash) {
  739. for(t = f->mount; t; t = t->next) {
  740. if(mw->mh == 0 ||
  741. (t->mountid > last && t->mountid < bestmid)) {
  742. mw->cm = t;
  743. mw->mh = f;
  744. bestmid = mw->cm->mountid;
  745. nxt = 1;
  746. }
  747. }
  748. }
  749. }
  750. if(nxt == 0)
  751. mw->mh = 0;
  752. runlock(&pg->ns);
  753. }
  754. static long
  755. procwrite(Chan *c, void *va, long n, vlong off)
  756. {
  757. int id, m;
  758. Proc *p, *t, *et;
  759. char *a, *arg, buf[ERRMAX];
  760. ulong offset = off;
  761. a = va;
  762. if(c->qid.type & QTDIR)
  763. error(Eisdir);
  764. p = proctab(SLOT(c->qid));
  765. /* Use the remembered noteid in the channel rather
  766. * than the process pgrpid
  767. */
  768. if(QID(c->qid) == Qnotepg) {
  769. pgrpnote(NOTEID(c->pgrpid), va, n, NUser);
  770. return n;
  771. }
  772. qlock(&p->debug);
  773. if(waserror()){
  774. qunlock(&p->debug);
  775. nexterror();
  776. }
  777. if(p->pid != PID(c->qid))
  778. error(Eprocdied);
  779. switch(QID(c->qid)){
  780. case Qargs:
  781. if(n == 0)
  782. error(Eshort);
  783. if(n >= ERRMAX)
  784. error(Etoobig);
  785. arg = malloc(n+1);
  786. if(arg == nil)
  787. error(Enomem);
  788. memmove(arg, va, n);
  789. m = n;
  790. if(arg[m-1] != 0)
  791. arg[m++] = 0;
  792. free(p->args);
  793. p->nargs = m;
  794. p->args = arg;
  795. p->setargs = 1;
  796. break;
  797. case Qmem:
  798. if(p->state != Stopped)
  799. error(Ebadctl);
  800. n = procctlmemio(p, offset, n, va, 0);
  801. break;
  802. case Qregs:
  803. if(offset >= sizeof(Ureg))
  804. return 0;
  805. if(offset+n > sizeof(Ureg))
  806. n = sizeof(Ureg) - offset;
  807. if(p->dbgreg == 0)
  808. error(Enoreg);
  809. setregisters(p->dbgreg, (char*)(p->dbgreg)+offset, va, n);
  810. break;
  811. case Qfpregs:
  812. if(offset >= sizeof(FPsave))
  813. return 0;
  814. if(offset+n > sizeof(FPsave))
  815. n = sizeof(FPsave) - offset;
  816. memmove((uchar*)&p->fpsave+offset, va, n);
  817. break;
  818. case Qctl:
  819. procctlreq(p, va, n);
  820. break;
  821. case Qnote:
  822. if(p->kp)
  823. error(Eperm);
  824. if(n >= ERRMAX-1)
  825. error(Etoobig);
  826. memmove(buf, va, n);
  827. buf[n] = 0;
  828. if(!postnote(p, 0, buf, NUser))
  829. error("note not posted");
  830. break;
  831. case Qnoteid:
  832. id = atoi(a);
  833. if(id == p->pid) {
  834. p->noteid = id;
  835. break;
  836. }
  837. t = proctab(0);
  838. for(et = t+conf.nproc; t < et; t++) {
  839. if(id == t->noteid) {
  840. if(strcmp(p->user, t->user) != 0)
  841. error(Eperm);
  842. p->noteid = id;
  843. break;
  844. }
  845. }
  846. if(p->noteid != id)
  847. error(Ebadarg);
  848. break;
  849. default:
  850. pprint("unknown qid in procwrite\n");
  851. error(Egreg);
  852. }
  853. poperror();
  854. qunlock(&p->debug);
  855. return n;
  856. }
  857. Dev procdevtab = {
  858. 'p',
  859. "proc",
  860. devreset,
  861. procinit,
  862. devshutdown,
  863. procattach,
  864. procwalk,
  865. procstat,
  866. procopen,
  867. devcreate,
  868. procclose,
  869. procread,
  870. devbread,
  871. procwrite,
  872. devbwrite,
  873. devremove,
  874. procwstat,
  875. };
  876. Chan*
  877. proctext(Chan *c, Proc *p)
  878. {
  879. Chan *tc;
  880. Image *i;
  881. Segment *s;
  882. s = p->seg[TSEG];
  883. if(s == 0)
  884. error(Enonexist);
  885. if(p->state==Dead)
  886. error(Eprocdied);
  887. lock(s);
  888. i = s->image;
  889. if(i == 0) {
  890. unlock(s);
  891. error(Eprocdied);
  892. }
  893. unlock(s);
  894. lock(i);
  895. if(waserror()) {
  896. unlock(i);
  897. nexterror();
  898. }
  899. tc = i->c;
  900. if(tc == 0)
  901. error(Eprocdied);
  902. if(incref(tc) == 1 || (tc->flag&COPEN) == 0 || tc->mode!=OREAD) {
  903. cclose(tc);
  904. error(Eprocdied);
  905. }
  906. if(p->pid != PID(c->qid))
  907. error(Eprocdied);
  908. unlock(i);
  909. poperror();
  910. return tc;
  911. }
  912. void
  913. procstopwait(Proc *p, int ctl)
  914. {
  915. int pid;
  916. if(p->pdbg)
  917. error(Einuse);
  918. if(procstopped(p) || p->state == Broken)
  919. return;
  920. if(ctl != 0)
  921. p->procctl = ctl;
  922. p->pdbg = up;
  923. pid = p->pid;
  924. qunlock(&p->debug);
  925. up->psstate = "Stopwait";
  926. if(waserror()) {
  927. p->pdbg = 0;
  928. qlock(&p->debug);
  929. nexterror();
  930. }
  931. sleep(&up->sleep, procstopped, p);
  932. poperror();
  933. qlock(&p->debug);
  934. if(p->pid != pid)
  935. error(Eprocdied);
  936. }
  937. static void
  938. procctlcloseone(Proc *p, Fgrp *f, int fd)
  939. {
  940. Chan *c;
  941. c = f->fd[fd];
  942. if(c == nil)
  943. return;
  944. f->fd[fd] = nil;
  945. unlock(f);
  946. qunlock(&p->debug);
  947. cclose(c);
  948. qlock(&p->debug);
  949. lock(f);
  950. }
  951. void
  952. procctlclosefiles(Proc *p, int all, int fd)
  953. {
  954. int i;
  955. Fgrp *f;
  956. f = p->fgrp;
  957. if(f == nil)
  958. error(Eprocdied);
  959. lock(f);
  960. f->ref++;
  961. if(all)
  962. for(i = 0; i < f->maxfd; i++)
  963. procctlcloseone(p, f, i);
  964. else
  965. procctlcloseone(p, f, fd);
  966. unlock(f);
  967. closefgrp(f);
  968. }
  969. void
  970. procctlreq(Proc *p, char *va, int n)
  971. {
  972. Segment *s;
  973. int i, npc;
  974. Cmdbuf *cb;
  975. Cmdtab *ct;
  976. if(p->kp) /* no ctl requests to kprocs */
  977. error(Eperm);
  978. cb = parsecmd(va, n);
  979. if(waserror()){
  980. free(cb);
  981. nexterror();
  982. }
  983. ct = lookupcmd(cb, proccmd, nelem(proccmd));
  984. switch(ct->index){
  985. case CMclose:
  986. procctlclosefiles(p, 0, atoi(cb->f[1]));
  987. break;
  988. case CMclosefiles:
  989. procctlclosefiles(p, 1, 0);
  990. break;
  991. case CMfixedpri:
  992. i = atoi(cb->f[1]);
  993. if(i < 0)
  994. i = 0;
  995. if(i >= Nrq)
  996. i = Nrq - 1;
  997. if(i > p->basepri && !iseve())
  998. error(Eperm);
  999. p->basepri = i;
  1000. p->fixedpri = 1;
  1001. break;
  1002. case CMhang:
  1003. p->hang = 1;
  1004. break;
  1005. case CMkill:
  1006. switch(p->state) {
  1007. case Broken:
  1008. unbreak(p);
  1009. break;
  1010. case Stopped:
  1011. postnote(p, 0, "sys: killed", NExit);
  1012. p->procctl = Proc_exitme;
  1013. ready(p);
  1014. break;
  1015. default:
  1016. postnote(p, 0, "sys: killed", NExit);
  1017. p->procctl = Proc_exitme;
  1018. }
  1019. break;
  1020. case CMnohang:
  1021. p->hang = 0;
  1022. break;
  1023. case CMnoswap:
  1024. p->noswap = 1;
  1025. break;
  1026. case CMpri:
  1027. i = atoi(cb->f[1]);
  1028. if(i < 0)
  1029. i = 0;
  1030. if(i >= Nrq)
  1031. i = Nrq - 1;
  1032. if(i > p->basepri && !iseve())
  1033. error(Eperm);
  1034. p->basepri = i;
  1035. p->fixedpri = 0;
  1036. break;
  1037. case CMprivate:
  1038. p->privatemem = 1;
  1039. break;
  1040. case CMprofile:
  1041. s = p->seg[TSEG];
  1042. if(s == 0 || (s->type&SG_TYPE) != SG_TEXT)
  1043. error(Ebadctl);
  1044. if(s->profile != 0)
  1045. free(s->profile);
  1046. npc = (s->top-s->base)>>LRESPROF;
  1047. s->profile = malloc(npc*sizeof(*s->profile));
  1048. if(s->profile == 0)
  1049. error(Enomem);
  1050. break;
  1051. case CMstart:
  1052. if(p->state != Stopped)
  1053. error(Ebadctl);
  1054. ready(p);
  1055. break;
  1056. case CMstartstop:
  1057. if(p->state != Stopped)
  1058. error(Ebadctl);
  1059. p->procctl = Proc_traceme;
  1060. ready(p);
  1061. procstopwait(p, Proc_traceme);
  1062. break;
  1063. case CMstop:
  1064. procstopwait(p, Proc_stopme);
  1065. break;
  1066. case CMwaitstop:
  1067. procstopwait(p, 0);
  1068. break;
  1069. case CMwired:
  1070. procwired(p, atoi(cb->f[1]));
  1071. break;
  1072. }
  1073. poperror();
  1074. free(cb);
  1075. }
  1076. int
  1077. procstopped(void *a)
  1078. {
  1079. Proc *p = a;
  1080. return p->state == Stopped;
  1081. }
  1082. int
  1083. procctlmemio(Proc *p, ulong offset, int n, void *va, int read)
  1084. {
  1085. KMap *k;
  1086. Pte *pte;
  1087. Page *pg;
  1088. Segment *s;
  1089. ulong soff, l;
  1090. char *a = va, *b;
  1091. for(;;) {
  1092. s = seg(p, offset, 1);
  1093. if(s == 0)
  1094. error(Ebadarg);
  1095. if(offset+n >= s->top)
  1096. n = s->top-offset;
  1097. if(!read && (s->type&SG_TYPE) == SG_TEXT)
  1098. s = txt2data(p, s);
  1099. s->steal++;
  1100. soff = offset-s->base;
  1101. if(waserror()) {
  1102. s->steal--;
  1103. nexterror();
  1104. }
  1105. if(fixfault(s, offset, read, 0) == 0)
  1106. break;
  1107. poperror();
  1108. s->steal--;
  1109. }
  1110. poperror();
  1111. pte = s->map[soff/PTEMAPMEM];
  1112. if(pte == 0)
  1113. panic("procctlmemio");
  1114. pg = pte->pages[(soff&(PTEMAPMEM-1))/BY2PG];
  1115. if(pagedout(pg))
  1116. panic("procctlmemio1");
  1117. l = BY2PG - (offset&(BY2PG-1));
  1118. if(n > l)
  1119. n = l;
  1120. k = kmap(pg);
  1121. if(waserror()) {
  1122. s->steal--;
  1123. kunmap(k);
  1124. nexterror();
  1125. }
  1126. b = (char*)VA(k);
  1127. b += offset&(BY2PG-1);
  1128. if(read == 1)
  1129. memmove(a, b, n); /* This can fault */
  1130. else
  1131. memmove(b, a, n);
  1132. kunmap(k);
  1133. poperror();
  1134. /* Ensure the process sees text page changes */
  1135. if(s->flushme)
  1136. memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
  1137. s->steal--;
  1138. if(read == 0)
  1139. p->newtlb = 1;
  1140. return n;
  1141. }
  1142. Segment*
  1143. txt2data(Proc *p, Segment *s)
  1144. {
  1145. int i;
  1146. Segment *ps;
  1147. ps = newseg(SG_DATA, s->base, s->size);
  1148. ps->image = s->image;
  1149. incref(ps->image);
  1150. ps->fstart = s->fstart;
  1151. ps->flen = s->flen;
  1152. ps->flushme = 1;
  1153. qlock(&p->seglock);
  1154. for(i = 0; i < NSEG; i++)
  1155. if(p->seg[i] == s)
  1156. break;
  1157. if(p->seg[i] != s)
  1158. panic("segment gone");
  1159. qunlock(&s->lk);
  1160. putseg(s);
  1161. qlock(&ps->lk);
  1162. p->seg[i] = ps;
  1163. qunlock(&p->seglock);
  1164. return ps;
  1165. }
  1166. Segment*
  1167. data2txt(Segment *s)
  1168. {
  1169. Segment *ps;
  1170. ps = newseg(SG_TEXT, s->base, s->size);
  1171. ps->image = s->image;
  1172. incref(ps->image);
  1173. ps->fstart = s->fstart;
  1174. ps->flen = s->flen;
  1175. ps->flushme = 1;
  1176. return ps;
  1177. }