Print this page
7029 want per-process exploit mitigation features (secflags)
7030 want basic address space layout randomization (aslr)
7031 noexec_user_stack should be a secflag
7032 want a means to forbid mappings around NULL.
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/priocntl/subr.c
+++ new/usr/src/cmd/priocntl/subr.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 -#pragma ident "%Z%%M% %I% %E% SMI"
28 -
29 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
30 28 /* All Rights Reserved */
31 29
32 30
33 31 #include <stdio.h>
34 32 #include <string.h>
35 33 #include <strings.h>
36 34 #include <stdlib.h>
37 35 #include <unistd.h>
38 36 #include <sys/types.h>
39 37 #include <limits.h>
40 38 #include <dirent.h>
41 39 #include <fcntl.h>
42 40 #include <sys/time.h>
43 41 #include <sys/procset.h>
44 42 #include <sys/priocntl.h>
45 43 #include <sys/task.h>
46 44 #include <procfs.h>
47 45 #include <project.h>
48 46 #include <errno.h>
49 47 #include <zone.h>
50 48 #include <libcontract_priv.h>
51 49
52 50 #include "priocntl.h"
53 51
54 52 /*LINTLIBRARY*/
55 53
56 54 /*
57 55 * Utility functions for priocntl command.
58 56 */
59 57
60 58 static char *procdir = "/proc";
61 59
62 60 /*PRINTFLIKE1*/
63 61 void
64 62 fatalerr(format, a1, a2, a3, a4, a5)
↓ open down ↓ |
26 lines elided |
↑ open up ↑ |
65 63 char *format;
66 64 int a1, a2, a3, a4, a5;
67 65 {
68 66 (void) fprintf(stderr, format, a1, a2, a3, a4, a5);
69 67 exit(1);
70 68 }
71 69
72 70
73 71 /*
74 72 * Structure defining idtypes known to the priocntl command
75 - * along with the corresponding names and a liberal guess
76 - * of the max number of procs sharing any given ID of that type.
73 + * along with the corresponding names
77 74 * The idtype values themselves are defined in <sys/procset.h>.
78 75 */
79 76 static struct idtypes {
80 77 idtype_t idtype;
81 78 char *idtypnm;
82 79 } idtypes [] = {
83 80 { P_PID, "pid" },
84 81 { P_PPID, "ppid" },
85 82 { P_PGID, "pgid" },
86 83 { P_SID, "sid" },
87 84 { P_CID, "class" },
88 85 { P_UID, "uid" },
89 86 { P_GID, "gid" },
90 87 { P_PROJID, "projid" },
91 88 { P_TASKID, "taskid" },
92 89 { P_ZONEID, "zoneid" },
93 90 { P_CTID, "ctid" },
94 91 { P_ALL, "all" }
95 92 };
96 93
97 94 #define IDCNT (sizeof (idtypes) / sizeof (struct idtypes))
98 95
99 96
100 97 int
101 98 str2idtyp(idtypnm, idtypep)
102 99 char *idtypnm;
103 100 idtype_t *idtypep;
104 101 {
105 102 register struct idtypes *curp;
106 103 register struct idtypes *endp;
107 104
108 105 for (curp = idtypes, endp = &idtypes[IDCNT]; curp < endp; curp++) {
109 106 if (strcmp(curp->idtypnm, idtypnm) == 0) {
110 107 *idtypep = curp->idtype;
111 108 return (0);
112 109 }
113 110 }
114 111 return (-1);
115 112 }
116 113
117 114
118 115 int
119 116 idtyp2str(idtype, idtypnm)
120 117 idtype_t idtype;
121 118 char *idtypnm;
122 119 {
123 120 register struct idtypes *curp;
124 121 register struct idtypes *endp;
125 122
126 123 for (curp = idtypes, endp = &idtypes[IDCNT]; curp < endp; curp++) {
127 124 if (idtype == curp->idtype) {
128 125 (void) strncpy(idtypnm, curp->idtypnm, PC_IDTYPNMSZ);
129 126 return (0);
130 127 }
131 128 }
132 129 return (-1);
133 130 }
134 131
135 132
136 133 /*
137 134 * Compare two IDs for equality.
138 135 */
139 136 int
140 137 idcompar(id1p, id2p)
141 138 id_t *id1p;
142 139 id_t *id2p;
143 140 {
144 141 if (*id1p == *id2p)
145 142 return (0);
146 143 else
147 144 return (-1);
148 145 }
149 146
150 147
151 148 id_t
152 149 clname2cid(clname)
153 150 char *clname;
154 151 {
155 152 pcinfo_t pcinfo;
156 153
157 154 (void) strncpy(pcinfo.pc_clname, clname, PC_CLNMSZ);
158 155 if (priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo) == -1)
159 156 return ((id_t)-1);
160 157 return (pcinfo.pc_cid);
161 158 }
162 159
163 160
164 161 int
165 162 getmyid(idtype, idptr)
166 163 idtype_t idtype;
167 164 id_t *idptr;
168 165 {
169 166 pcinfo_t pcinfo;
170 167
171 168 switch (idtype) {
172 169
173 170 case P_PID:
174 171 *idptr = (id_t)getpid();
175 172 break;
176 173
177 174 case P_PPID:
178 175 *idptr = (id_t)getppid();
179 176 break;
180 177
181 178 case P_PGID:
182 179 *idptr = (id_t)getpgrp();
183 180 break;
184 181
185 182 case P_SID:
186 183 *idptr = (id_t)getsid(getpid());
187 184 break;
188 185
189 186 case P_CID:
190 187 if (priocntl(P_PID, P_MYID, PC_GETXPARMS, NULL,
191 188 PC_KY_CLNAME, pcinfo.pc_clname, 0) == -1 ||
192 189 priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo) == -1)
193 190 return (-1);
194 191
195 192 *idptr = pcinfo.pc_cid;
196 193 break;
197 194
198 195 case P_UID:
199 196 *idptr = (id_t)getuid();
200 197 break;
201 198
202 199 case P_GID:
203 200 *idptr = (id_t)getgid();
204 201 break;
205 202
206 203 case P_PROJID:
207 204 *idptr = (id_t)getprojid();
208 205 break;
209 206
210 207 case P_TASKID:
211 208 *idptr = (id_t)gettaskid();
212 209 break;
213 210
214 211 case P_ZONEID:
215 212 *idptr = (id_t)getzoneid();
216 213 break;
217 214
218 215 case P_CTID: {
219 216 ctid_t id = getctid();
220 217 if (id == -1)
221 218 return (-1);
222 219 *idptr = id;
223 220 break;
224 221 }
225 222
226 223 default:
227 224 return (-1);
228 225 }
229 226 return (0);
230 227 }
231 228
232 229
233 230 int
234 231 getmyidstr(idtype, idstr)
235 232 idtype_t idtype;
236 233 char *idstr;
237 234 {
238 235 char clname[PC_CLNMSZ];
239 236
240 237 switch (idtype) {
241 238
242 239 case P_PID:
243 240 itoa((long)getpid(), idstr);
244 241 break;
245 242
246 243 case P_PPID:
247 244 itoa((long)getppid(), idstr);
248 245 break;
249 246
250 247 case P_PGID:
251 248 itoa((long)getpgrp(), idstr);
252 249 break;
253 250 case P_SID:
254 251 itoa((long)getsid(getpid()), idstr);
255 252 break;
256 253
257 254 case P_CID:
258 255 if (priocntl(P_PID, P_MYID, PC_GETXPARMS, NULL,
259 256 PC_KY_CLNAME, clname, 0) == -1)
260 257 return (-1);
261 258 (void) strncpy(idstr, clname, PC_CLNMSZ);
262 259 break;
263 260
264 261 case P_UID:
265 262 itoa((long)getuid(), idstr);
266 263 break;
267 264
268 265 case P_GID:
269 266 itoa((long)getgid(), idstr);
270 267 break;
271 268
272 269 case P_PROJID:
273 270 itoa((long)getprojid(), idstr);
274 271 break;
275 272
276 273 case P_TASKID:
277 274 itoa((long)gettaskid(), idstr);
278 275 break;
279 276
280 277 case P_ZONEID:
281 278 itoa((long)getzoneid(), idstr);
282 279 break;
283 280
284 281 case P_CTID: {
285 282 id_t id;
286 283 if ((id = getctid()) == -1)
287 284 return (-1);
288 285 itoa((long)id, idstr);
289 286 break;
290 287 }
291 288
292 289 default:
293 290 return (-1);
294 291 }
295 292 return (0);
296 293 }
297 294
298 295 /*
299 296 * Look for pids with "upri > uprilim" in the set specified by idtype/id.
300 297 * If upri exceeds uprilim then print a warning.
301 298 */
302 299 int
303 300 verifyupri(idtype_t idtype, id_t id, char *clname, int key,
304 301 pri_t upri, char *basenm)
305 302 {
306 303 psinfo_t prinfo;
307 304 prcred_t prcred;
308 305 DIR *dirp;
309 306 struct dirent *dentp;
310 307 char pname[MAXNAMLEN];
311 308 char *fname;
312 309 int procfd;
313 310 int saverr;
314 311 pri_t uprilim;
315 312 int verify;
316 313 int error = 0;
317 314
318 315 if (idtype == P_PID) {
319 316 if (priocntl(P_PID, id, PC_GETXPARMS, clname, key,
320 317 &uprilim, 0) == -1)
321 318 error = -1;
322 319 else if (upri > uprilim)
323 320 (void) fprintf(stderr,
324 321 "%s: Specified user priority %d exceeds"
325 322 " limit %d; set to %d (pid %d)\n",
326 323 basenm, upri, uprilim, uprilim, (int)id);
327 324
328 325 return (error);
329 326 }
330 327
331 328 /*
332 329 * Look for the processes in the set specified by idtype/id.
333 330 * We read the /proc/<pid>/psinfo file to get the necessary
334 331 * process information.
335 332 */
336 333
337 334 if ((dirp = opendir(procdir)) == NULL)
338 335 fatalerr("%s: Can't open PROC directory %s\n",
339 336 basenm, procdir);
340 337
341 338 while ((dentp = readdir(dirp)) != NULL) {
342 339 if (dentp->d_name[0] == '.') /* skip . and .. */
343 340 continue;
344 341
345 342 (void) snprintf(pname, MAXNAMLEN, "%s/%s/",
346 343 procdir, dentp->d_name);
347 344 fname = pname + strlen(pname);
348 345 retry:
349 346 (void) strncpy(fname, "psinfo", strlen("psinfo") + 1);
350 347 if ((procfd = open(pname, O_RDONLY)) < 0)
351 348 continue;
352 349 if (read(procfd, &prinfo, sizeof (prinfo)) != sizeof (prinfo)) {
353 350 saverr = errno;
354 351 (void) close(procfd);
355 352 if (saverr == EAGAIN)
356 353 goto retry;
357 354 continue;
358 355 }
359 356 (void) close(procfd);
360 357
361 358 if (idtype == P_UID || idtype == P_GID) {
362 359 (void) strncpy(fname, "cred", strlen("cred") + 1);
363 360 if ((procfd = open(pname, O_RDONLY)) < 0 ||
364 361 read(procfd, &prcred, sizeof (prcred)) !=
365 362 sizeof (prcred)) {
366 363 saverr = errno;
367 364 (void) close(procfd);
368 365 if (saverr == EAGAIN)
369 366 goto retry;
370 367 continue;
371 368 }
372 369 (void) close(procfd);
373 370 }
374 371
375 372 if (prinfo.pr_lwp.pr_state == 0 || prinfo.pr_nlwp == 0)
376 373 continue;
377 374
378 375 /*
379 376 * The lwp must be in the correct class.
380 377 */
381 378 if (strncmp(clname, prinfo.pr_lwp.pr_clname, PC_CLNMSZ) != 0)
382 379 continue;
383 380
384 381 verify = 0;
385 382 switch (idtype) {
386 383
387 384 case P_PPID:
388 385 if (id == (id_t)prinfo.pr_ppid)
389 386 verify++;
390 387 break;
391 388
392 389 case P_PGID:
393 390 if (id == (id_t)prinfo.pr_pgid)
394 391 verify++;
395 392 break;
396 393
397 394 case P_SID:
398 395 if (id == (id_t)prinfo.pr_sid)
399 396 verify++;
400 397 break;
401 398
402 399 case P_UID:
403 400 if (id == (id_t)prcred.pr_euid)
404 401 verify++;
405 402 break;
406 403
407 404 case P_GID:
408 405 if (id == (id_t)prcred.pr_egid)
409 406 verify++;
410 407 break;
411 408
412 409 case P_PROJID:
413 410 if (id == (id_t)prinfo.pr_projid)
414 411 verify++;
415 412 break;
416 413
417 414 case P_TASKID:
418 415 if (id == (id_t)prinfo.pr_taskid)
419 416 verify++;
420 417 break;
421 418
422 419 case P_ZONEID:
423 420 if (id == (id_t)prinfo.pr_zoneid)
424 421 verify++;
425 422 break;
426 423
427 424 case P_CTID:
428 425 if (id == (id_t)prinfo.pr_contract)
429 426 verify++;
430 427 break;
431 428
432 429 case P_CID:
433 430 case P_ALL:
434 431 verify++;
435 432 break;
436 433
437 434 default:
438 435 fatalerr("%s: Bad idtype %d in verifyupri()\n",
439 436 basenm, idtype);
440 437 }
441 438
442 439 if (verify) {
443 440 if (priocntl(P_PID, prinfo.pr_pid, PC_GETXPARMS,
444 441 clname, key, &uprilim, 0) == -1)
445 442 error = -1;
446 443 else if (upri > uprilim)
447 444 (void) fprintf(stderr,
448 445 "%s: Specified user priority %d exceeds"
449 446 " limit %d; set to %d (pid %d)\n",
450 447 basenm, upri, uprilim, uprilim,
451 448 (int)prinfo.pr_pid);
452 449 }
453 450 }
454 451 (void) closedir(dirp);
455 452
456 453 return (error);
457 454 }
458 455
459 456
460 457 /*
461 458 * Read a list of pids from a stream.
462 459 */
463 460 pid_t *
464 461 read_pidlist(size_t *npidsp, FILE *filep)
465 462 {
466 463 size_t nitems;
467 464 pid_t *pidlist = NULL;
468 465
469 466 *npidsp = 0;
470 467
471 468 do {
472 469 if ((pidlist = (pid_t *)realloc(pidlist,
473 470 (*npidsp + NPIDS) * sizeof (pid_t))) == NULL)
474 471 return (NULL);
475 472
476 473 nitems = fread(pidlist + *npidsp, sizeof (pid_t), NPIDS, filep);
477 474 if (ferror(filep))
478 475 return (NULL);
479 476
480 477 *npidsp += nitems;
481 478 } while (nitems == NPIDS);
482 479
483 480 return (pidlist);
484 481 }
485 482
486 483
487 484 void
488 485 free_pidlist(pid_t *pidlist)
489 486 {
490 487 free(pidlist);
491 488 }
492 489
493 490
494 491 long
495 492 str2num(char *p, long min, long max)
496 493 {
497 494 long val;
498 495 char *q;
499 496 errno = 0;
500 497
501 498 val = strtol(p, &q, 10);
502 499 if (errno != 0 || q == p || *q != '\0' || val < min || val > max)
503 500 errno = EINVAL;
504 501
505 502 return (val);
506 503 }
507 504
508 505
509 506 /*
510 507 * itoa() and reverse() taken almost verbatim from K & R Chapter 3.
511 508 */
512 509 static void reverse();
513 510
514 511 /*
515 512 * itoa(): Convert n to characters in s.
516 513 */
517 514 void
518 515 itoa(n, s)
519 516 long n;
520 517 char *s;
521 518 {
522 519 long i, sign;
523 520
524 521 if ((sign = n) < 0) /* record sign */
525 522 n = -n; /* make sign positive */
526 523 i = 0;
527 524 do { /* generate digits in reverse order */
528 525 s[i++] = n % 10 + '0'; /* get next digit */
529 526 } while ((n /= 10) > 0); /* delete it */
530 527 if (sign < 0)
531 528 s[i++] = '-';
532 529 s[i] = '\0';
533 530 reverse(s);
534 531 }
535 532
536 533
537 534 /*
538 535 * reverse(): Reverse string s in place.
539 536 */
540 537 static void
541 538 reverse(s)
542 539 char *s;
543 540 {
544 541 int c, i, j;
545 542
546 543 for (i = 0, j = strlen(s) - 1; i < j; i++, j--) {
547 544 c = s[i];
548 545 s[i] = s[j];
549 546 s[j] = (char)c;
550 547 }
551 548 }
552 549
553 550
554 551 /*
555 552 * The following routine was removed from libc (libc/port/gen/hrtnewres.c).
556 553 * It has also been added to disadmin, so if you fix it here, you should
557 554 * also probably fix it there. In the long term, this should be recoded to
558 555 * not be hrt'ish.
559 556 */
560 557
561 558 /*
562 559 * Convert interval expressed in htp->hrt_res to new_res.
563 560 *
564 561 * Calculate: (interval * new_res) / htp->hrt_res rounding off as
565 562 * specified by round.
566 563 *
567 564 * Note: All args are assumed to be positive. If
568 565 * the last divide results in something bigger than
569 566 * a long, then -1 is returned instead.
570 567 */
571 568
572 569 int
573 570 _hrtnewres(htp, new_res, round)
574 571 register hrtimer_t *htp;
575 572 register ulong_t new_res;
576 573 long round;
577 574 {
578 575 register long interval;
579 576 longlong_t dint;
580 577 longlong_t dto_res;
581 578 longlong_t drem;
582 579 longlong_t dfrom_res;
583 580 longlong_t prod;
584 581 longlong_t quot;
585 582 register long numerator;
586 583 register long result;
587 584 ulong_t modulus;
588 585 ulong_t twomodulus;
589 586 long temp;
590 587
591 588 if (new_res > NANOSEC || htp->hrt_rem < 0)
592 589 return (-1);
593 590
594 591 if (htp->hrt_rem >= htp->hrt_res) {
595 592 htp->hrt_secs += htp->hrt_rem / htp->hrt_res;
596 593 htp->hrt_rem = htp->hrt_rem % htp->hrt_res;
597 594 }
598 595
599 596 interval = htp->hrt_rem;
600 597 if (interval == 0) {
601 598 htp->hrt_res = new_res;
602 599 return (0);
603 600 }
604 601
605 602 /*
606 603 * Try to do the calculations in single precision first
607 604 * (for speed). If they overflow, use double precision.
608 605 * What we want to compute is:
609 606 *
610 607 * (interval * new_res) / hrt->hrt_res
611 608 */
612 609
613 610 numerator = interval * new_res;
614 611
615 612 if (numerator / new_res == interval) {
616 613
617 614 /*
618 615 * The above multiply didn't give overflow since
619 616 * the division got back the original number. Go
620 617 * ahead and compute the result.
621 618 */
622 619
623 620 result = numerator / htp->hrt_res;
624 621
625 622 /*
626 623 * For HRT_RND, compute the value of:
627 624 *
628 625 * (interval * new_res) % htp->hrt_res
629 626 *
630 627 * If it is greater than half of the htp->hrt_res,
631 628 * then rounding increases the result by 1.
632 629 *
633 630 * For HRT_RNDUP, we increase the result by 1 if:
634 631 *
635 632 * result * htp->hrt_res != numerator
636 633 *
637 634 * because this tells us we truncated when calculating
638 635 * result above.
639 636 *
640 637 * We also check for overflow when incrementing result
641 638 * although this is extremely rare.
642 639 */
643 640
644 641 if (round == HRT_RND) {
645 642 modulus = numerator - result * htp->hrt_res;
646 643 if ((twomodulus = 2 * modulus) / 2 == modulus) {
647 644
648 645 /*
649 646 * No overflow (if we overflow in calculation
650 647 * of twomodulus we fall through and use
651 648 * double precision).
652 649 */
653 650 if (twomodulus >= htp->hrt_res) {
654 651 temp = result + 1;
655 652 if (temp - 1 == result)
656 653 result++;
657 654 else
658 655 return (-1);
659 656 }
660 657 htp->hrt_res = new_res;
661 658 htp->hrt_rem = result;
662 659 return (0);
663 660 }
664 661 } else if (round == HRT_RNDUP) {
665 662 if (result * htp->hrt_res != numerator) {
666 663 temp = result + 1;
667 664 if (temp - 1 == result)
668 665 result++;
669 666 else
670 667 return (-1);
671 668 }
672 669 htp->hrt_res = new_res;
673 670 htp->hrt_rem = result;
674 671 return (0);
675 672 } else { /* round == HRT_TRUNC */
676 673 htp->hrt_res = new_res;
677 674 htp->hrt_rem = result;
678 675 return (0);
679 676 }
680 677 }
681 678
682 679 /*
683 680 * We would get overflow doing the calculation is
684 681 * single precision so do it the slow but careful way.
685 682 *
686 683 * Compute the interval times the resolution we are
687 684 * going to.
688 685 */
689 686
690 687 dint = interval;
691 688 dto_res = new_res;
692 689 prod = dint * dto_res;
693 690
694 691 /*
695 692 * For HRT_RND the result will be equal to:
696 693 *
697 694 * ((interval * new_res) + htp->hrt_res / 2) / htp->hrt_res
698 695 *
699 696 * and for HRT_RNDUP we use:
700 697 *
701 698 * ((interval * new_res) + htp->hrt_res - 1) / htp->hrt_res
702 699 *
703 700 * This is a different but equivalent way of rounding.
704 701 */
705 702
706 703 if (round == HRT_RND) {
707 704 drem = htp->hrt_res / 2;
708 705 prod = prod + drem;
709 706 } else if (round == HRT_RNDUP) {
710 707 drem = htp->hrt_res - 1;
711 708 prod = prod + drem;
712 709 }
713 710
714 711 dfrom_res = htp->hrt_res;
715 712 quot = prod / dfrom_res;
716 713
717 714 /*
718 715 * If the quotient won't fit in a long, then we have
719 716 * overflow. Otherwise, return the result.
720 717 */
721 718
722 719 if (quot > UINT_MAX) {
723 720 return (-1);
724 721 } else {
725 722 htp->hrt_res = new_res;
726 723 htp->hrt_rem = (int)quot;
727 724 return (0);
728 725 }
729 726 }
↓ open down ↓ |
643 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX