Print this page
6139 help gcc figure out variable initialization
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/modload/plcysubr.c
+++ new/usr/src/cmd/modload/plcysubr.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
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 *
26 26 * Device policy specific subroutines. We cannot merge them with
27 27 * drvsubr.c because of static linking requirements.
28 28 */
29 29
30 -#pragma ident "%Z%%M% %I% %E% SMI"
31 -
32 30 #include <stdio.h>
33 31 #include <stdlib.h>
34 32 #include <unistd.h>
35 33 #include <string.h>
36 34 #include <ctype.h>
37 35 #include <priv.h>
38 36 #include <string.h>
39 37 #include <libgen.h>
40 38 #include <libintl.h>
41 39 #include <errno.h>
42 40 #include <alloca.h>
43 41 #include <sys/modctl.h>
44 42 #include <sys/devpolicy.h>
45 43 #include <sys/stat.h>
46 44 #include <sys/sysmacros.h>
47 45
48 46 #include "addrem.h"
49 47 #include "errmsg.h"
50 48 #include "plcysubr.h"
51 49
52 50 size_t devplcysys_sz;
53 51 const priv_impl_info_t *privimplinfo;
54 52
55 53 /*
56 54 * New token types should be parsed in parse_plcy_entry.
57 55 */
58 56 #define PSET 0
59 57
60 58 typedef struct token {
61 59 const char *token;
62 60 int type;
63 61 ptrdiff_t off;
64 62 } token_t;
65 63
66 64 static token_t toktab[] = {
67 65 { DEVPLCY_TKN_RDP, PSET /* offsetof(devplcysys_t, dps_rdp) */ },
68 66 { DEVPLCY_TKN_WRP, PSET /* offsetof(devplcysys_t, dps_wrp) */ },
69 67 };
70 68
71 69 #define RDPOL 0
72 70 #define WRPOL 1
73 71
74 72 #define NTOK (sizeof (toktab)/sizeof (token_t))
75 73
76 74 /*
77 75 * Compute the size of the datastructures needed.
78 76 */
79 77 void
80 78 devplcy_init(void)
81 79 {
82 80 if ((privimplinfo = getprivimplinfo()) == NULL) {
83 81 (void) fprintf(stderr, gettext(ERR_PRIVIMPL));
84 82 exit(1);
85 83 }
86 84
87 85 devplcysys_sz = DEVPLCYSYS_SZ(privimplinfo);
88 86
89 87 toktab[RDPOL].off =
90 88 (char *)DEVPLCYSYS_RDP((devplcysys_t *)0, privimplinfo) -
91 89 (char *)0;
92 90 toktab[WRPOL].off =
93 91 (char *)DEVPLCYSYS_WRP((devplcysys_t *)0, privimplinfo) -
94 92 (char *)0;
95 93 }
96 94
97 95 /*
98 96 * Read a configuration file line and return a static buffer pointing to it.
99 97 * It returns a static struct fileentry which has several fields:
100 98 * - rawbuf, which includes the lines including empty lines and comments
101 99 * leading up to the file and the entry as found in the file
102 100 * - orgentry, pointer in rawbuf to the start of the entry proper.
103 101 * - entry, a pre-parsed entry, escaped newlines removed.
104 102 * - startline, the line number of the first line in the file
105 103 */
106 104 fileentry_t *
107 105 fgetline(FILE *fp)
108 106 {
109 107 static size_t sz = BUFSIZ;
110 108 static struct fileentry fe;
111 109 static int linecnt = 1;
112 110
113 111 char *buf = fe.rawbuf;
114 112 ptrdiff_t off;
115 113 char *p;
116 114 int c, lastc, i;
117 115
118 116 if (buf == NULL) {
119 117 fe.rawbuf = buf = malloc(sz);
120 118 if (buf == NULL)
121 119 return (NULL);
122 120 }
123 121 if (fe.entry != NULL) {
124 122 free(fe.entry);
125 123 fe.orgentry = fe.entry = NULL;
126 124 }
127 125
128 126 i = 0;
129 127 off = -1;
130 128 c = '\n';
131 129
132 130 while (lastc = c, (c = getc(fp)) != EOF) {
133 131 buf[i++] = c;
134 132
135 133 if (i == sz) {
136 134 sz *= 2;
137 135 fe.rawbuf = buf = realloc(buf, sz);
138 136 if (buf == NULL)
139 137 return (NULL);
140 138 }
141 139
142 140 if (c == '\n') {
143 141 linecnt++;
144 142 /* Newline, escaped or not yet processing an entry */
145 143 if (off == -1 || lastc == '\\')
146 144 continue;
147 145 } else if (lastc == '\n' && off == -1) {
148 146 /* Start of more comments */
149 147 if (c == '#')
150 148 continue;
151 149 /* Found start of entry */
152 150 off = i - 1;
153 151 fe.startline = linecnt;
154 152 continue;
155 153 } else
156 154 continue;
157 155
158 156 buf[i] = '\0';
159 157 fe.orgentry = buf + off;
160 158 p = fe.entry = strdup(fe.orgentry);
161 159
162 160 if (p == NULL)
163 161 return (NULL);
164 162
165 163 /* Remove <backslash><newline> */
166 164 if ((p = strchr(p, '\\')) != NULL) {
167 165 for (off = 0; (p[-off] = p[0]) != '\0'; p++)
168 166 if (p[0] == '\\' && p[1] == '\n') {
169 167 off += 2;
170 168 p++;
171 169 }
172 170 }
173 171 return (&fe);
174 172 }
175 173 if (lastc != '\n' || off != -1)
176 174 return (NULL);
177 175 buf[i] = '\0';
178 176 linecnt = 1;
179 177 return (&fe);
180 178 }
181 179
182 180 /*
183 181 * Parse minor number ranges:
184 182 * (minor) or (lowminor-highminor)
185 183 * Return 0 for success, -1 for failure.
186 184 */
187 185 int
188 186 parse_minor_range(const char *range, minor_t *lo, minor_t *hi, char *type)
189 187 {
190 188 unsigned long tmp;
191 189 char *p;
192 190
193 191 if (*range++ != '(')
194 192 return (-1);
195 193
196 194 errno = 0;
197 195 tmp = strtoul(range, &p, 0);
198 196 if (tmp > L_MAXMIN32 || (tmp == 0 && errno != 0) ||
199 197 (*p != '-' && *p != ')'))
200 198 return (-1);
201 199 *lo = tmp;
202 200 if (*p == '-') {
203 201 errno = 0;
204 202 tmp = strtoul(p + 1, &p, 0);
205 203 if (tmp > L_MAXMIN32 || (tmp == 0 && errno != 0) || *p != ')')
206 204 return (-1);
207 205 }
208 206 *hi = tmp;
209 207 if (*lo > *hi)
210 208 return (-1);
211 209
212 210 switch (p[1]) {
213 211 case '\0':
214 212 *type = '\0';
215 213 break;
216 214 case 'c':
217 215 case 'C':
218 216 *type = 'c';
219 217 break;
220 218 case 'b':
221 219 case 'B':
222 220 *type = 'b';
223 221 break;
224 222 default:
225 223 return (-1);
226 224 }
227 225 return (0);
228 226 }
229 227
230 228 static void
231 229 put_minor_range(FILE *fp, fileentry_t *old, const char *devn, const char *tail,
232 230 minor_t lo, minor_t hi, char type)
233 231 {
234 232 /* Preserve preceeding comments */
235 233 if (old != NULL && old->rawbuf != old->orgentry)
236 234 (void) fwrite(old->rawbuf, 1, old->orgentry - old->rawbuf, fp);
237 235
238 236 if (type == '\0') {
239 237 put_minor_range(fp, NULL, devn, tail, lo, hi, 'b');
240 238 put_minor_range(fp, NULL, devn, tail, lo, hi, 'c');
241 239 } else if (lo == hi) {
242 240 (void) fprintf(fp, "%s:(%d)%c%s", devn, (int)lo, type, tail);
243 241 } else {
244 242 (void) fprintf(fp, "%s:(%d-%d)%c%s", devn, (int)lo, (int)hi,
245 243 type, tail);
246 244 }
247 245 }
248 246
249 247 static int
250 248 delete_one_entry(const char *filename, const char *entry)
251 249 {
252 250 char tfile[MAXPATHLEN];
253 251 char ofile[MAXPATHLEN];
254 252 char *nfile;
255 253 FILE *old, *new;
256 254 fileentry_t *fep;
257 255 struct stat buf;
258 256 int newfd;
259 257 char *mpart;
260 258 boolean_t delall;
261 259 boolean_t delrange;
262 260 minor_t rlo, rhi;
263 261 char rtype;
264 262
265 263 mpart = strchr(entry, ':');
266 264 if (mpart == NULL) {
267 265 delall = B_TRUE;
268 266 delrange = B_FALSE;
269 267 } else {
270 268 delall = B_FALSE;
271 269 mpart++;
272 270 if (*mpart == '(') {
273 271 if (parse_minor_range(mpart, &rlo, &rhi, &rtype) != 0)
274 272 return (-1);
275 273 delrange = B_TRUE;
276 274 } else {
277 275 delrange = B_FALSE;
278 276 }
279 277 }
280 278
281 279 if (strlen(filename) + sizeof (XEND) > sizeof (tfile))
282 280 return (-1);
283 281
284 282 old = fopen(filename, "r");
285 283
286 284 if (old == NULL)
287 285 return (-1);
288 286
289 287 (void) snprintf(tfile, sizeof (tfile), "%s%s", filename, XEND);
290 288 (void) snprintf(ofile, sizeof (ofile), "%s%s", filename, ".old");
291 289
292 290 nfile = mktemp(tfile);
293 291
294 292 new = fopen(nfile, "w");
295 293 if (new == NULL) {
296 294 (void) fclose(old);
297 295 return (ERROR);
298 296 }
299 297
300 298 newfd = fileno(new);
301 299
302 300 /* Copy permissions, ownership */
303 301 if (fstat(fileno(old), &buf) == 0) {
304 302 (void) fchown(newfd, buf.st_uid, buf.st_gid);
305 303 (void) fchmod(newfd, buf.st_mode);
306 304 } else {
307 305 (void) fchown(newfd, 0, 3); /* root:sys */
308 306 (void) fchmod(newfd, 0644);
309 307 }
310 308
311 309 while ((fep = fgetline(old))) {
312 310 char *tok;
313 311 char *min;
314 312 char *tail;
315 313 char tc;
316 314 int len;
317 315
318 316 /* Trailing comments */
319 317 if (fep->entry == NULL) {
320 318 (void) fputs(fep->rawbuf, new);
321 319 break;
322 320 }
323 321
324 322 tok = fep->entry;
325 323 while (*tok && isspace(*tok))
326 324 tok++;
327 325
328 326 if (*tok == '\0') {
329 327 (void) fputs(fep->rawbuf, new);
↓ open down ↓ |
288 lines elided |
↑ open up ↑ |
330 328 break;
331 329 }
332 330
333 331 /* Make sure we can recover the remainder incl. whitespace */
334 332 tail = strpbrk(tok, "\t\n ");
335 333 if (tail == NULL)
336 334 tail = tok + strlen(tok);
337 335 tc = *tail;
338 336 *tail = '\0';
339 337
340 - if (delall || delrange) {
341 - min = strchr(tok, ':');
342 - if (min)
343 - *min++ = '\0';
344 - }
338 + min = strchr(tok, ':');
339 + if (min && (delall || delrange))
340 + *min++ = '\0';
345 341
346 342 len = strlen(tok);
347 343 if (delrange) {
348 344 minor_t lo, hi;
349 345 char type;
350 346
351 347 /*
352 348 * Delete or shrink overlapping ranges.
353 349 */
354 350 if (strncmp(entry, tok, len) == 0 &&
355 351 entry[len] == ':' &&
356 352 min != NULL &&
357 353 parse_minor_range(min, &lo, &hi, &type) == 0 &&
358 354 (type == rtype || rtype == '\0') &&
359 355 lo <= rhi && hi >= rlo) {
360 356 minor_t newlo, newhi;
361 357
362 358 /* Complete overlap, then drop it. */
363 359 if (lo >= rlo && hi <= rhi)
364 360 continue;
365 361
366 362 /* Partial overlap, shrink range */
367 363 if (lo < rlo)
368 364 newhi = rlo - 1;
369 365 else
370 366 newhi = hi;
371 367 if (hi > rhi)
372 368 newlo = rhi + 1;
373 369 else
374 370 newlo = lo;
375 371
376 372 /* restore NULed character */
377 373 *tail = tc;
378 374
379 375 /* Split range? */
380 376 if (newlo > newhi) {
381 377 /*
382 378 * We have two ranges:
383 379 * lo ... newhi (== rlo - 1)
384 380 * newlo (== rhi + 1) .. hi
385 381 */
386 382 put_minor_range(new, fep, tok, tail,
387 383 lo, newhi, type);
388 384 put_minor_range(new, NULL, tok, tail,
389 385 newlo, hi, type);
390 386 } else {
391 387 put_minor_range(new, fep, tok, tail,
392 388 newlo, newhi, type);
393 389 }
394 390 continue;
395 391 }
396 392 } else if (strcmp(entry, tok) == 0 ||
397 393 (strncmp(entry, tok, len) == 0 &&
398 394 entry[len] == ':' &&
399 395 entry[len+1] == '*' &&
400 396 entry[len+2] == '\0')) {
401 397 /*
402 398 * Delete exact match.
403 399 */
404 400 continue;
405 401 }
406 402
407 403 /* Copy unaffected entry. */
408 404 (void) fputs(fep->rawbuf, new);
409 405 }
410 406 (void) fclose(old);
411 407 (void) fflush(new);
412 408 (void) fsync(newfd);
413 409 if (ferror(new) == 0 && fclose(new) == 0 && fep != NULL) {
414 410 if (rename(filename, ofile) != 0) {
415 411 perror(NULL);
416 412 (void) fprintf(stderr, gettext(ERR_UPDATE), ofile);
417 413 (void) unlink(ofile);
418 414 (void) unlink(nfile);
419 415 return (ERROR);
420 416 } else if (rename(nfile, filename) != 0) {
421 417 perror(NULL);
422 418 (void) fprintf(stderr, gettext(ERR_UPDATE), ofile);
423 419 (void) rename(ofile, filename);
424 420 (void) unlink(nfile);
425 421 return (ERROR);
426 422 }
427 423 (void) unlink(ofile);
428 424 } else
429 425 (void) unlink(nfile);
430 426 return (0);
431 427 }
432 428
433 429
434 430 int
435 431 delete_plcy_entry(const char *filename, const char *entry)
436 432 {
437 433 char *p, *single;
438 434 char *copy;
439 435 int ret = 0;
440 436
441 437 copy = strdup(entry);
442 438 if (copy == NULL)
443 439 return (ERROR);
444 440
445 441 for (single = strtok_r(copy, " \t\n", &p);
446 442 single != NULL;
447 443 single = strtok_r(NULL, " \t\n", &p)) {
448 444 if ((ret = delete_one_entry(filename, single)) != 0) {
449 445 free(copy);
450 446 return (ret);
451 447 }
452 448 }
453 449 free(copy);
454 450 return (0);
455 451 }
456 452
457 453 /*
458 454 * Analyze the device policy token; new tokens should be added to
459 455 * toktab; new token types should be coded here.
460 456 */
461 457 int
462 458 parse_plcy_token(char *token, devplcysys_t *dp)
463 459 {
464 460 char *val = strchr(token, '=');
465 461 const char *perr;
466 462 int i;
467 463 priv_set_t *pset;
468 464
469 465 if (val == NULL) {
470 466 (void) fprintf(stderr, gettext(ERR_NO_EQUALS), token);
471 467 return (1);
472 468 }
473 469 *val++ = '\0';
474 470
475 471 for (i = 0; i < NTOK; i++) {
476 472 if (strcmp(token, toktab[i].token) == 0) {
477 473 /* standard pointer computation for tokens */
478 474 void *item = (char *)dp + toktab[i].off;
479 475
480 476 switch (toktab[i].type) {
481 477 case PSET:
482 478 pset = priv_str_to_set(val, ",", &perr);
483 479 if (pset == NULL) {
484 480 if (perr == NULL)
485 481 (void) fprintf(stderr,
486 482 gettext(ERR_NO_MEM));
487 483 else
488 484 (void) fprintf(stderr,
489 485 gettext(ERR_BAD_PRIVS),
490 486 perr - val, val, perr);
491 487 return (1);
492 488 }
493 489 priv_copyset(pset, item);
494 490 priv_freeset(pset);
495 491 break;
496 492 default:
497 493 (void) fprintf(stderr,
498 494 "Internal Error: bad token type: %d\n",
499 495 toktab[i].type);
500 496 return (1);
501 497 }
502 498 /* Standard cleanup & return for good tokens */
503 499 val[-1] = '=';
504 500 return (0);
505 501 }
506 502 }
507 503 (void) fprintf(stderr, gettext(ERR_BAD_TOKEN), token);
508 504 return (1);
509 505 }
510 506
511 507 static int
512 508 add2str(char **dstp, const char *str, size_t *sz)
513 509 {
514 510 char *p = *dstp;
515 511 size_t len = strlen(p) + strlen(str) + 1;
516 512
517 513 if (len > *sz) {
518 514 *sz *= 2;
519 515 if (*sz < len)
520 516 *sz = len;
521 517 *dstp = p = realloc(p, *sz);
522 518 if (p == NULL) {
523 519 (void) fprintf(stderr, gettext(ERR_NO_MEM));
524 520 return (-1);
525 521 }
526 522 }
527 523 (void) strcat(p, str);
528 524 return (0);
529 525 }
530 526
531 527 /*
532 528 * Verify that the policy entry is valid and return the canonical entry.
533 529 */
534 530 char *
535 531 check_plcy_entry(char *entry, const char *driver, boolean_t todel)
536 532 {
537 533 char *res;
538 534 devplcysys_t *ds;
539 535 char *tok;
540 536 size_t sz = strlen(entry) * 2 + strlen(driver) + 3;
541 537 boolean_t tokseen = B_FALSE;
542 538
543 539 devplcy_init();
544 540
545 541 res = malloc(sz);
546 542 ds = alloca(devplcysys_sz);
547 543
548 544 if (res == NULL || ds == NULL) {
549 545 (void) fprintf(stderr, gettext(ERR_NO_MEM));
550 546 return (NULL);
551 547 }
552 548
553 549 *res = '\0';
554 550
555 551 while ((tok = strtok(entry, " \t\n")) != NULL) {
556 552 entry = NULL;
557 553
558 554 /* It's not a token */
559 555 if (strchr(tok, '=') == NULL) {
560 556 if (strchr(tok, ':') != NULL) {
561 557 (void) fprintf(stderr, gettext(ERR_BAD_MINOR));
562 558 free(res);
563 559 return (NULL);
564 560 }
565 561 if (*res != '\0' && add2str(&res, "\n", &sz) != 0)
566 562 return (NULL);
567 563
568 564 if (*tok == '(') {
569 565 char type;
570 566 if (parse_minor_range(tok, &ds->dps_lomin,
571 567 &ds->dps_himin, &type) != 0 ||
572 568 (!todel && type == '\0')) {
573 569 (void) fprintf(stderr,
574 570 gettext(ERR_BAD_MINOR));
575 571 free(res);
576 572 return (NULL);
577 573 }
578 574 } else {
579 575 char *tmp = strchr(tok, '*');
580 576
581 577 if (tmp != NULL &&
582 578 strchr(tmp + 1, '*') != NULL) {
583 579 (void) fprintf(stderr,
584 580 gettext(ERR_BAD_MINOR));
585 581 free(res);
586 582 }
587 583 }
588 584
589 585 if (add2str(&res, driver, &sz) != 0)
590 586 return (NULL);
591 587 if (add2str(&res, ":", &sz) != 0)
592 588 return (NULL);
593 589 if (add2str(&res, tok, &sz) != 0)
594 590 return (NULL);
595 591 tokseen = B_FALSE;
596 592 } else {
597 593 if (*res == '\0') {
598 594 if (add2str(&res, driver, &sz) != 0)
599 595 return (NULL);
600 596 if (add2str(&res, ":*", &sz) != 0)
601 597 return (NULL);
602 598 }
603 599 if (parse_plcy_token(tok, ds) != 0) {
604 600 free(res);
605 601 return (NULL);
606 602 }
607 603
608 604 if (add2str(&res, "\t", &sz) != 0)
609 605 return (NULL);
610 606 if (add2str(&res, tok, &sz) != 0)
611 607 return (NULL);
612 608 tokseen = B_TRUE;
613 609 }
614 610 }
615 611 if (todel && tokseen || *res == '\0' || !todel && !tokseen) {
616 612 (void) fprintf(stderr, gettext(ERR_INVALID_PLCY));
617 613 free(res);
618 614 return (NULL);
619 615 }
620 616 if (!todel)
621 617 if (add2str(&res, "\n", &sz) != 0)
622 618 return (NULL);
623 619 return (res);
624 620 }
625 621
626 622 int
627 623 update_device_policy(const char *filename, const char *entry, boolean_t repl)
628 624 {
629 625 FILE *fp;
630 626
631 627 if (repl) {
632 628 char *dup, *tok, *s1;
633 629
634 630 dup = strdup(entry);
635 631 if (dup == NULL) {
636 632 (void) fprintf(stderr, gettext(ERR_NO_MEM));
637 633 return (ERROR);
638 634 }
639 635
640 636 /*
641 637 * Split the entry in lines; then get the first token
642 638 * of each line.
643 639 */
644 640 for (tok = strtok_r(dup, "\n", &s1); tok != NULL;
645 641 tok = strtok_r(NULL, "\n", &s1)) {
646 642
647 643 tok = strtok(tok, " \n\t");
648 644
649 645 if (delete_one_entry(filename, tok) != 0) {
650 646 free(dup);
651 647 return (ERROR);
652 648 }
653 649 }
654 650
655 651 free(dup);
656 652 }
657 653
658 654 fp = fopen(filename, "a");
659 655 if (fp == NULL)
660 656 return (ERROR);
661 657
662 658 (void) fputs(entry, fp);
663 659
664 660 if (fflush(fp) != 0 || fsync(fileno(fp)) != 0 || fclose(fp) != 0)
665 661 return (ERROR);
666 662
667 663 return (NOERR);
668 664 }
669 665
670 666
671 667 /*
672 668 * We need to allocate the privileges now or the privilege set
673 669 * parsing code will not allow them.
674 670 */
675 671 int
676 672 check_priv_entry(const char *privlist, boolean_t add)
677 673 {
678 674 char *l = strdup(privlist);
679 675 char *pr;
680 676
681 677 if (l == NULL) {
682 678 (void) fprintf(stderr, gettext(ERR_NO_MEM));
683 679 return (ERROR);
684 680 }
685 681
686 682 while ((pr = strtok_r(l, ",", &l)) != NULL) {
687 683 /* Privilege already exists */
688 684 if (priv_getbyname(pr) != -1)
689 685 continue;
690 686
691 687 if (add && modctl(MODALLOCPRIV, pr) != 0) {
692 688 (void) fprintf(stderr, gettext(ERR_BAD_PRIV), pr,
693 689 strerror(errno));
694 690 return (ERROR);
695 691 }
696 692 }
697 693 return (NOERR);
698 694 }
↓ open down ↓ |
344 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX