devfs_rule.c (149107) | devfs_rule.c (150147) |
---|---|
1/*- 2 * Copyright (c) 2002 Dima Dorfman. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * | 1/*- 2 * Copyright (c) 2002 Dima Dorfman. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * |
26 * $FreeBSD: head/sys/fs/devfs/devfs_rule.c 149107 2005-08-15 19:40:53Z phk $ | 26 * $FreeBSD: head/sys/fs/devfs/devfs_rule.c 150147 2005-09-15 06:57:28Z phk $ |
27 */ 28 29/* 30 * DEVFS ruleset implementation. 31 * 32 * A note on terminology: To "run" a rule on a dirent is to take the 33 * prescribed action; to "apply" a rule is to check whether it matches 34 * a dirent and run if if it does. --- 56 unchanged lines hidden (view full) --- 91 */ 92struct devfs_ruleset { 93 SLIST_ENTRY(devfs_ruleset) ds_list; 94 devfs_rsnum ds_number; 95 SLIST_HEAD(, devfs_krule) ds_rules; 96 int ds_refcount; 97 int ds_flags; 98#define DS_IMMUTABLE 0x001 | 27 */ 28 29/* 30 * DEVFS ruleset implementation. 31 * 32 * A note on terminology: To "run" a rule on a dirent is to take the 33 * prescribed action; to "apply" a rule is to check whether it matches 34 * a dirent and run if if it does. --- 56 unchanged lines hidden (view full) --- 91 */ 92struct devfs_ruleset { 93 SLIST_ENTRY(devfs_ruleset) ds_list; 94 devfs_rsnum ds_number; 95 SLIST_HEAD(, devfs_krule) ds_rules; 96 int ds_refcount; 97 int ds_flags; 98#define DS_IMMUTABLE 0x001 |
99 int ds_running; | |
100}; 101 102static devfs_rid devfs_rid_input(devfs_rid rid, struct devfs_mount *dm); 103 | 99}; 100 101static devfs_rid devfs_rid_input(devfs_rid rid, struct devfs_mount *dm); 102 |
104static void devfs_rule_applyde(struct devfs_krule *dk,struct devfs_dirent *de); | |
105static void devfs_rule_applyde_recursive(struct devfs_krule *dk, 106 struct devfs_dirent *de); 107static void devfs_rule_applydm(struct devfs_krule *dk, struct devfs_mount *dm); 108static int devfs_rule_autonumber(struct devfs_ruleset *ds, devfs_rnum *rnp); 109static struct devfs_krule *devfs_rule_byid(devfs_rid rid); 110static int devfs_rule_delete(struct devfs_krule **dkp); 111static struct cdev *devfs_rule_getdev(struct devfs_dirent *de); 112static int devfs_rule_input(struct devfs_rule *dr, struct devfs_mount *dm); 113static int devfs_rule_insert(struct devfs_rule *dr); 114static int devfs_rule_match(struct devfs_krule *dk, struct devfs_dirent *de); 115static int devfs_rule_matchpath(struct devfs_krule *dk, 116 struct devfs_dirent *de); | 103static void devfs_rule_applyde_recursive(struct devfs_krule *dk, 104 struct devfs_dirent *de); 105static void devfs_rule_applydm(struct devfs_krule *dk, struct devfs_mount *dm); 106static int devfs_rule_autonumber(struct devfs_ruleset *ds, devfs_rnum *rnp); 107static struct devfs_krule *devfs_rule_byid(devfs_rid rid); 108static int devfs_rule_delete(struct devfs_krule **dkp); 109static struct cdev *devfs_rule_getdev(struct devfs_dirent *de); 110static int devfs_rule_input(struct devfs_rule *dr, struct devfs_mount *dm); 111static int devfs_rule_insert(struct devfs_rule *dr); 112static int devfs_rule_match(struct devfs_krule *dk, struct devfs_dirent *de); 113static int devfs_rule_matchpath(struct devfs_krule *dk, 114 struct devfs_dirent *de); |
117static void devfs_rule_run(struct devfs_krule *dk, struct devfs_dirent *de); | 115static void devfs_rule_run(struct devfs_krule *dk, struct devfs_dirent *de, unsigned depth); |
118 119static void devfs_ruleset_applyde(struct devfs_ruleset *ds, | 116 117static void devfs_ruleset_applyde(struct devfs_ruleset *ds, |
120 struct devfs_dirent *de); | 118 struct devfs_dirent *de, unsigned depth); |
121static void devfs_ruleset_applydm(struct devfs_ruleset *ds, 122 struct devfs_mount *dm); 123static struct devfs_ruleset *devfs_ruleset_bynum(devfs_rsnum rsnum); 124static struct devfs_ruleset *devfs_ruleset_create(devfs_rsnum rsnum); 125static void devfs_ruleset_destroy(struct devfs_ruleset **dsp); 126static void devfs_ruleset_reap(struct devfs_ruleset **dsp); 127static int devfs_ruleset_use(devfs_rsnum rsnum, struct devfs_mount *dm); 128 129static SLIST_HEAD(, devfs_ruleset) devfs_rulesets; 130 131/* | 119static void devfs_ruleset_applydm(struct devfs_ruleset *ds, 120 struct devfs_mount *dm); 121static struct devfs_ruleset *devfs_ruleset_bynum(devfs_rsnum rsnum); 122static struct devfs_ruleset *devfs_ruleset_create(devfs_rsnum rsnum); 123static void devfs_ruleset_destroy(struct devfs_ruleset **dsp); 124static void devfs_ruleset_reap(struct devfs_ruleset **dsp); 125static int devfs_ruleset_use(devfs_rsnum rsnum, struct devfs_mount *dm); 126 127static SLIST_HEAD(, devfs_ruleset) devfs_rulesets; 128 129/* |
132 * Called to apply the proper rules for de before the latter can be | 130 * Called to apply the proper rules for 'de' before it can be |
133 * exposed to the userland. This should be called with an exclusive 134 * lock on dm in case we need to run anything. 135 */ 136void 137devfs_rules_apply(struct devfs_mount *dm, struct devfs_dirent *de) 138{ 139 struct devfs_ruleset *ds; 140 141 ds = devfs_ruleset_bynum(dm->dm_ruleset); 142 KASSERT(ds != NULL, ("mount-point has NULL ruleset")); | 131 * exposed to the userland. This should be called with an exclusive 132 * lock on dm in case we need to run anything. 133 */ 134void 135devfs_rules_apply(struct devfs_mount *dm, struct devfs_dirent *de) 136{ 137 struct devfs_ruleset *ds; 138 139 ds = devfs_ruleset_bynum(dm->dm_ruleset); 140 KASSERT(ds != NULL, ("mount-point has NULL ruleset")); |
143 devfs_ruleset_applyde(ds, de); | 141 devfs_ruleset_applyde(ds, de, devfs_rule_depth); |
144} 145 146/* 147 * Rule subsystem SYSINIT hook. 148 */ 149static void 150devfs_rules_init(void *junk __unused) 151{ --- 211 unchanged lines hidden (view full) --- 363 364 if (rid2rsn(rid) == 0) 365 return (mkrid(dm->dm_ruleset, rid2rn(rid))); 366 else 367 return (rid); 368} 369 370/* | 142} 143 144/* 145 * Rule subsystem SYSINIT hook. 146 */ 147static void 148devfs_rules_init(void *junk __unused) 149{ --- 211 unchanged lines hidden (view full) --- 361 362 if (rid2rsn(rid) == 0) 363 return (mkrid(dm->dm_ruleset, rid2rn(rid))); 364 else 365 return (rid); 366} 367 368/* |
371 * Apply dk to de. 372 */ 373static void 374devfs_rule_applyde(struct devfs_krule *dk, struct devfs_dirent *de) 375{ 376 377 if (devfs_rule_match(dk, de)) 378 devfs_rule_run(dk, de); 379} 380 381/* | |
382 * Apply dk to de and everything under de. 383 * 384 * XXX: This method needs a function call for every nested 385 * subdirectory in a devfs mount. If we plan to have many of these, 386 * we might eventually run out of kernel stack space. 387 */ 388static void 389devfs_rule_applyde_recursive(struct devfs_krule *dk, struct devfs_dirent *de) 390{ 391 struct devfs_dirent *de2; 392 | 369 * Apply dk to de and everything under de. 370 * 371 * XXX: This method needs a function call for every nested 372 * subdirectory in a devfs mount. If we plan to have many of these, 373 * we might eventually run out of kernel stack space. 374 */ 375static void 376devfs_rule_applyde_recursive(struct devfs_krule *dk, struct devfs_dirent *de) 377{ 378 struct devfs_dirent *de2; 379 |
393 /* XXX: Should we apply to ourselves first or last? Does it matter? */ 394 TAILQ_FOREACH(de2, &de->de_dlist, de_list) { | 380 TAILQ_FOREACH(de2, &de->de_dlist, de_list) |
395 devfs_rule_applyde_recursive(dk, de2); | 381 devfs_rule_applyde_recursive(dk, de2); |
396 } 397 devfs_rule_applyde(dk, de); | 382 devfs_rule_run(dk, de, devfs_rule_depth); |
398} 399 400/* 401 * Apply dk to all entires in dm. 402 */ 403static void 404devfs_rule_applydm(struct devfs_krule *dk, struct devfs_mount *dm) 405{ --- 199 unchanged lines hidden (view full) --- 605 * *not* match, since the default is to assume the rule should 606 * be run (such as if there are no conditions). 607 * 608 * XXX: lacks threadref on dev 609 */ 610 if (dr->dr_icond & DRC_DSWFLAGS) 611 if (dev == NULL || 612 (dev->si_devsw->d_flags & dr->dr_dswflags) == 0) | 383} 384 385/* 386 * Apply dk to all entires in dm. 387 */ 388static void 389devfs_rule_applydm(struct devfs_krule *dk, struct devfs_mount *dm) 390{ --- 199 unchanged lines hidden (view full) --- 590 * *not* match, since the default is to assume the rule should 591 * be run (such as if there are no conditions). 592 * 593 * XXX: lacks threadref on dev 594 */ 595 if (dr->dr_icond & DRC_DSWFLAGS) 596 if (dev == NULL || 597 (dev->si_devsw->d_flags & dr->dr_dswflags) == 0) |
613 goto nomatch; | 598 return (0); |
614 if (dr->dr_icond & DRC_PATHPTRN) 615 if (!devfs_rule_matchpath(dk, de)) | 599 if (dr->dr_icond & DRC_PATHPTRN) 600 if (!devfs_rule_matchpath(dk, de)) |
616 goto nomatch; | 601 return (0); |
617 618 return (1); | 602 603 return (1); |
619 620nomatch: 621 return (0); | |
622} 623 624/* 625 * Determine whether dk matches de on account of dr_pathptrn. 626 */ 627static int 628devfs_rule_matchpath(struct devfs_krule *dk, struct devfs_dirent *de) 629{ --- 13 unchanged lines hidden (view full) --- 643 644 return (fnmatch(dr->dr_pathptrn, pname, 0) == 0); 645} 646 647/* 648 * Run dk on de. 649 */ 650static void | 604} 605 606/* 607 * Determine whether dk matches de on account of dr_pathptrn. 608 */ 609static int 610devfs_rule_matchpath(struct devfs_krule *dk, struct devfs_dirent *de) 611{ --- 13 unchanged lines hidden (view full) --- 625 626 return (fnmatch(dr->dr_pathptrn, pname, 0) == 0); 627} 628 629/* 630 * Run dk on de. 631 */ 632static void |
651devfs_rule_run(struct devfs_krule *dk, struct devfs_dirent *de) | 633devfs_rule_run(struct devfs_krule *dk, struct devfs_dirent *de, unsigned depth) |
652{ 653 struct devfs_rule *dr = &dk->dk_rule; 654 struct devfs_ruleset *ds; 655 | 634{ 635 struct devfs_rule *dr = &dk->dk_rule; 636 struct devfs_ruleset *ds; 637 |
638 if (!devfs_rule_match(dk, de)) 639 return; |
|
656 if (dr->dr_iacts & DRA_BACTS) { 657 if (dr->dr_bacts & DRB_HIDE) 658 de->de_flags |= DE_WHITEOUT; 659 if (dr->dr_bacts & DRB_UNHIDE) 660 de->de_flags &= ~DE_WHITEOUT; 661 } 662 if (dr->dr_iacts & DRA_UID) 663 de->de_uid = dr->dr_uid; 664 if (dr->dr_iacts & DRA_GID) 665 de->de_gid = dr->dr_gid; 666 if (dr->dr_iacts & DRA_MODE) 667 de->de_mode = dr->dr_mode; 668 if (dr->dr_iacts & DRA_INCSET) { | 640 if (dr->dr_iacts & DRA_BACTS) { 641 if (dr->dr_bacts & DRB_HIDE) 642 de->de_flags |= DE_WHITEOUT; 643 if (dr->dr_bacts & DRB_UNHIDE) 644 de->de_flags &= ~DE_WHITEOUT; 645 } 646 if (dr->dr_iacts & DRA_UID) 647 de->de_uid = dr->dr_uid; 648 if (dr->dr_iacts & DRA_GID) 649 de->de_gid = dr->dr_gid; 650 if (dr->dr_iacts & DRA_MODE) 651 de->de_mode = dr->dr_mode; 652 if (dr->dr_iacts & DRA_INCSET) { |
669 ds = devfs_ruleset_bynum(dk->dk_rule.dr_incset); 670 KASSERT(ds != NULL, ("DRA_INCSET but bad dr_incset")); 671 if (ds->ds_running) 672 printf("Warning: avoiding loop through ruleset %d\n", 673 ds->ds_number); 674 else 675 devfs_ruleset_applyde(ds, de); | 653 /* 654 * XXX: we should tell the user if the depth is exceeded here 655 * XXX: but it is not obvious how to. A return value will 656 * XXX: not work as this is called when devices are created 657 * XXX: long time after the rules were instantiated. 658 * XXX: a printf() would probably give too much noise, or 659 * XXX: DoS the machine. I guess a a rate-limited message 660 * XXX: might work. 661 */ 662 if (depth > 0) { 663 ds = devfs_ruleset_bynum(dk->dk_rule.dr_incset); 664 KASSERT(ds != NULL, ("DRA_INCSET but bad dr_incset")); 665 devfs_ruleset_applyde(ds, de, depth - 1); 666 } |
676 } 677} 678 679/* 680 * Apply all the rules in ds to de. 681 */ 682static void | 667 } 668} 669 670/* 671 * Apply all the rules in ds to de. 672 */ 673static void |
683devfs_ruleset_applyde(struct devfs_ruleset *ds, struct devfs_dirent *de) | 674devfs_ruleset_applyde(struct devfs_ruleset *ds, struct devfs_dirent *de, unsigned depth) |
684{ 685 struct devfs_krule *dk; 686 | 675{ 676 struct devfs_krule *dk; 677 |
687 KASSERT(!ds->ds_running,("ruleset %d already running", ds->ds_number)); 688 ds->ds_running = 1; 689 SLIST_FOREACH(dk, &ds->ds_rules, dk_list) { 690 devfs_rule_applyde(dk, de); 691 } 692 ds->ds_running = 0; | 678 SLIST_FOREACH(dk, &ds->ds_rules, dk_list) 679 devfs_rule_run(dk, de, depth); |
693} 694 695/* 696 * Apply all the rules in ds to all the entires in dm. 697 */ 698static void 699devfs_ruleset_applydm(struct devfs_ruleset *ds, struct devfs_mount *dm) 700{ 701 struct devfs_krule *dk; 702 | 680} 681 682/* 683 * Apply all the rules in ds to all the entires in dm. 684 */ 685static void 686devfs_ruleset_applydm(struct devfs_ruleset *ds, struct devfs_mount *dm) 687{ 688 struct devfs_krule *dk; 689 |
703 KASSERT(!ds->ds_running,("ruleset %d already running", ds->ds_number)); 704 ds->ds_running = 1; | |
705 /* 706 * XXX: Does it matter whether we do 707 * 708 * foreach(dk in ds) 709 * foreach(de in dm) 710 * apply(dk to de) 711 * 712 * as opposed to 713 * 714 * foreach(de in dm) 715 * foreach(dk in ds) 716 * apply(dk to de) 717 * 718 * The end result is obviously the same, but does the order 719 * matter? 720 */ 721 SLIST_FOREACH(dk, &ds->ds_rules, dk_list) { 722 devfs_rule_applydm(dk, dm); 723 } | 690 /* 691 * XXX: Does it matter whether we do 692 * 693 * foreach(dk in ds) 694 * foreach(de in dm) 695 * apply(dk to de) 696 * 697 * as opposed to 698 * 699 * foreach(de in dm) 700 * foreach(dk in ds) 701 * apply(dk to de) 702 * 703 * The end result is obviously the same, but does the order 704 * matter? 705 */ 706 SLIST_FOREACH(dk, &ds->ds_rules, dk_list) { 707 devfs_rule_applydm(dk, dm); 708 } |
724 ds->ds_running = 0; | |
725} 726 727/* 728 * Find a ruleset by number. 729 */ 730static struct devfs_ruleset * 731devfs_ruleset_bynum(devfs_rsnum rsnum) 732{ --- 100 unchanged lines hidden --- | 709} 710 711/* 712 * Find a ruleset by number. 713 */ 714static struct devfs_ruleset * 715devfs_ruleset_bynum(devfs_rsnum rsnum) 716{ --- 100 unchanged lines hidden --- |