devproc.c 23 KB

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