Deleted Added
full compact
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 ---