xref: /freebsd/sys/fs/devfs/devfs_rule.c (revision 3642298923e528d795e3a30ec165d2b469e28b40)
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  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
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$
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.
35  *
36  * A note on locking: Only foreign entry points (non-static functions)
37  * should deal with locking.  Everything else assumes we already hold
38  * the required kind of lock.
39  *
40  * A note on namespace: devfs_rules_* are the non-static functions for
41  * the entire "ruleset" subsystem, devfs_rule_* are the static
42  * functions that operate on rules, and devfs_ruleset_* are the static
43  * functions that operate on rulesets.  The line between the last two
44  * isn't always clear, but the guideline is still useful.
45  *
46  * A note on "special" identifiers: Ruleset 0 is the NULL, or empty,
47  * ruleset; it cannot be deleted or changed in any way.  This may be
48  * assumed inside the code; e.g., a ruleset of 0 may be interpeted to
49  * mean "no ruleset".  The interpretation of rule 0 is
50  * command-dependent, but in no case is there a real rule with number
51  * 0.
52  *
53  * A note on errno codes: To make it easier for the userland to tell
54  * what went wrong, we sometimes use errno codes that are not entirely
55  * appropriate for the error but that would be less ambiguous than the
56  * appropriate "generic" code.  For example, when we can't find a
57  * ruleset, we return ESRCH instead of ENOENT (except in
58  * DEVFSIO_{R,S}GETNEXT, where a nonexistent ruleset means "end of
59  * list", and the userland expects ENOENT to be this indicator); this
60  * way, when an operation fails, it's clear that what couldn't be
61  * found is a ruleset and not a rule (well, it's clear to those who
62  * know the convention).
63  */
64 
65 #include "opt_devfs.h"
66 
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/conf.h>
70 #include <sys/kernel.h>
71 #include <sys/malloc.h>
72 #include <sys/dirent.h>
73 #include <sys/vnode.h>
74 #include <sys/ioccom.h>
75 #include <sys/sx.h>
76 
77 #include <fs/devfs/devfs.h>
78 
79 
80 /*
81  * Kernel version of devfs_rule.
82  */
83 struct devfs_krule {
84 	SLIST_ENTRY(devfs_krule) dk_list;
85 	struct devfs_ruleset *dk_ruleset;
86 	struct devfs_rule dk_rule;
87 };
88 
89 /*
90  * Structure to describe a ruleset.
91  */
92 struct 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 };
100 
101 static devfs_rid devfs_rid_input(devfs_rid rid, struct devfs_mount *dm);
102 
103 static void devfs_rule_applyde_recursive(struct devfs_krule *dk,
104 		struct devfs_dirent *de);
105 static void devfs_rule_applydm(struct devfs_krule *dk, struct devfs_mount *dm);
106 static int  devfs_rule_autonumber(struct devfs_ruleset *ds, devfs_rnum *rnp);
107 static struct devfs_krule *devfs_rule_byid(devfs_rid rid);
108 static int  devfs_rule_delete(struct devfs_krule **dkp);
109 static struct cdev *devfs_rule_getdev(struct devfs_dirent *de);
110 static int  devfs_rule_input(struct devfs_rule *dr, struct devfs_mount *dm);
111 static int  devfs_rule_insert(struct devfs_rule *dr);
112 static int  devfs_rule_match(struct devfs_krule *dk, struct devfs_dirent *de);
113 static int  devfs_rule_matchpath(struct devfs_krule *dk,
114 		struct devfs_dirent *de);
115 static void devfs_rule_run(struct devfs_krule *dk, struct devfs_dirent *de, unsigned depth);
116 
117 static void devfs_ruleset_applyde(struct devfs_ruleset *ds,
118 		struct devfs_dirent *de, unsigned depth);
119 static void devfs_ruleset_applydm(struct devfs_ruleset *ds,
120 		struct devfs_mount *dm);
121 static struct devfs_ruleset *devfs_ruleset_bynum(devfs_rsnum rsnum);
122 static struct devfs_ruleset *devfs_ruleset_create(devfs_rsnum rsnum);
123 static void devfs_ruleset_destroy(struct devfs_ruleset **dsp);
124 static void devfs_ruleset_reap(struct devfs_ruleset **dsp);
125 static int  devfs_ruleset_use(devfs_rsnum rsnum, struct devfs_mount *dm);
126 
127 static struct sx sx_rules;
128 static SLIST_HEAD(, devfs_ruleset) devfs_rulesets;
129 
130 /*
131  * Called to apply the proper rules for 'de' before it can be
132  * exposed to the userland.  This should be called with an exclusive
133  * lock on dm in case we need to run anything.
134  */
135 void
136 devfs_rules_apply(struct devfs_mount *dm, struct devfs_dirent *de)
137 {
138 	struct devfs_ruleset *ds;
139 
140 	sx_slock(&sx_rules);
141 	ds = devfs_ruleset_bynum(dm->dm_ruleset);
142 	KASSERT(ds != NULL, ("mount-point has NULL ruleset"));
143 	devfs_ruleset_applyde(ds, de, devfs_rule_depth);
144 	sx_sunlock(&sx_rules);
145 }
146 
147 /*
148  * Rule subsystem SYSINIT hook.
149  */
150 static void
151 devfs_rules_init(void *junk __unused)
152 {
153 	struct devfs_ruleset *ds;
154 
155 	sx_init(&sx_rules, "devfsrules");
156 	SLIST_INIT(&devfs_rulesets);
157 
158 	ds = devfs_ruleset_create(0);
159 	ds->ds_flags |= DS_IMMUTABLE;
160 	ds->ds_refcount = 1;		/* Prevent reaping. */
161 }
162 
163 SYSINIT(devfs_rules, SI_SUB_DEVFS, SI_ORDER_FIRST, devfs_rules_init, NULL);
164 
165 /*
166  * Rule subsystem ioctl hook.
167  */
168 int
169 devfs_rules_ioctl(struct devfs_mount *dm, u_long cmd, caddr_t data, struct thread *td)
170 {
171 	struct devfs_ruleset *ds;
172 	struct devfs_krule *dk;
173 	struct devfs_rule *dr;
174 	devfs_rsnum rsnum;
175 	devfs_rnum rnum;
176 	devfs_rid rid;
177 	int error;
178 
179 	/*
180 	 * XXX: This returns an error regardless of whether we
181 	 * actually support the cmd or not.
182 	 */
183 	error = suser(td);
184 	if (error != 0)
185 		return (error);
186 
187 	sx_xlock(&sx_rules);
188 	switch (cmd) {
189 	case DEVFSIO_RADD:
190 		dr = (struct devfs_rule *)data;
191 		error = devfs_rule_input(dr, dm);
192 		if (error != 0)
193 			goto out;
194 		dk = devfs_rule_byid(dr->dr_id);
195 		if (dk != NULL) {
196 			error = EEXIST;
197 			goto out;
198 		}
199 		error = devfs_rule_insert(dr);
200 		break;
201 	case DEVFSIO_RAPPLY:
202 		dr = (struct devfs_rule *)data;
203 		error = devfs_rule_input(dr, dm);
204 		if (error != 0)
205 			goto out;
206 
207 		/*
208 		 * This is one of many possible hackish
209 		 * implementations.  The primary contender is an
210 		 * implementation where the rule we read in is
211 		 * temporarily inserted into some ruleset, perhaps
212 		 * with a hypothetical DRO_NOAUTO flag so that it
213 		 * doesn't get used where it isn't intended, and
214 		 * applied in the normal way.  This can be done in the
215 		 * userland (DEVFSIO_ADD, DEVFSIO_APPLYID,
216 		 * DEVFSIO_DEL) or in the kernel; either way it breaks
217 		 * some corner case assumptions in other parts of the
218 		 * code (not that this implementation doesn't do
219 		 * that).
220 		 */
221 		if (dr->dr_iacts & DRA_INCSET &&
222 		    devfs_ruleset_bynum(dr->dr_incset) == NULL) {
223 			error = ESRCH;
224 			goto out;
225 		}
226 		dk = malloc(sizeof(*dk), M_TEMP, M_WAITOK | M_ZERO);
227 		memcpy(&dk->dk_rule, dr, sizeof(*dr));
228 		devfs_rule_applydm(dk, dm);
229 		free(dk, M_TEMP);
230 		error = 0;
231 		break;
232 	case DEVFSIO_RAPPLYID:
233 		rid = *(devfs_rid *)data;
234 		rid = devfs_rid_input(rid, dm);
235 		dk = devfs_rule_byid(rid);
236 		if (dk == NULL) {
237 			error = ENOENT;
238 			goto out;
239 		}
240 		devfs_rule_applydm(dk, dm);
241 		error = 0;
242 		break;
243 	case DEVFSIO_RDEL:
244 		rid = *(devfs_rid *)data;
245 		rid = devfs_rid_input(rid, dm);
246 		dk = devfs_rule_byid(rid);
247 		if (dk == NULL) {
248 			error = ENOENT;
249 			goto out;
250 		}
251 		ds = dk->dk_ruleset;
252 		error = devfs_rule_delete(&dk);
253 		devfs_ruleset_reap(&ds);
254 		break;
255 	case DEVFSIO_RGETNEXT:
256 		dr = (struct devfs_rule *)data;
257 		error = devfs_rule_input(dr, dm);
258 		if (error != 0)
259 			goto out;
260 		/*
261 		 * We can't use devfs_rule_byid() here since that
262 		 * requires the rule specified to exist, but we want
263 		 * getnext(N) to work whether there is a rule N or not
264 		 * (specifically, getnext(0) must work, but we should
265 		 * never have a rule 0 since the add command
266 		 * interprets 0 to mean "auto-number").
267 		 */
268 		ds = devfs_ruleset_bynum(rid2rsn(dr->dr_id));
269 		if (ds == NULL) {
270 			error = ENOENT;
271 			goto out;
272 		}
273 		rnum = rid2rn(dr->dr_id);
274 		SLIST_FOREACH(dk, &ds->ds_rules, dk_list) {
275 			if (rid2rn(dk->dk_rule.dr_id) > rnum)
276 				break;
277 		}
278 		if (dk == NULL) {
279 			error = ENOENT;
280 			goto out;
281 		}
282 		memcpy(dr, &dk->dk_rule, sizeof(*dr));
283 		error = 0;
284 		break;
285 	case DEVFSIO_SUSE:
286 		rsnum = *(devfs_rsnum *)data;
287 		error = devfs_ruleset_use(rsnum, dm);
288 		break;
289 	case DEVFSIO_SAPPLY:
290 		rsnum = *(devfs_rsnum *)data;
291 		rsnum = rid2rsn(devfs_rid_input(mkrid(rsnum, 0), dm));
292 		ds = devfs_ruleset_bynum(rsnum);
293 		if (ds == NULL) {
294 			error = ESRCH;
295 			goto out;
296 		}
297 		devfs_ruleset_applydm(ds, dm);
298 		error = 0;
299 		break;
300 	case DEVFSIO_SGETNEXT:
301 		rsnum = *(devfs_rsnum *)data;
302 		SLIST_FOREACH(ds, &devfs_rulesets, ds_list) {
303 			if (ds->ds_number > rsnum)
304 				break;
305 		}
306 		if (ds == NULL)
307 			error = ENOENT;
308 		else {
309 			*(devfs_rsnum *)data = ds->ds_number;
310 			error = 0;
311 		}
312 		break;
313 	default:
314 		error = ENOIOCTL;
315 		break;
316 	}
317 
318 out:
319 	sx_xunlock(&sx_rules);
320 	return (error);
321 }
322 
323 /*
324  * Called to initialize dm_ruleset when there is a new mount-point.
325  */
326 void
327 devfs_rules_newmount(struct devfs_mount *dm, struct thread *td)
328 {
329 	struct devfs_ruleset *ds;
330 
331 	/*
332 	 * We can't use devfs_ruleset_use() since it will try to
333 	 * decrement the refcount for the old ruleset, and there is no
334 	 * old ruleset.  Making some value of ds_ruleset "special" to
335 	 * mean "don't decrement refcount" is uglier than this.
336 	 */
337 	sx_slock(&sx_rules);
338 	ds = devfs_ruleset_bynum(0);
339 	KASSERT(ds != NULL, ("no ruleset 0"));
340 	++ds->ds_refcount;
341 	dm->dm_ruleset = 0;
342 	sx_sunlock(&sx_rules);
343 }
344 
345 /*
346  * Adjust the rule identifier to use the ruleset of dm if one isn't
347  * explicitly specified.
348  *
349  * Note that after this operation, rid2rsn(rid) might still be 0, and
350  * that's okay; ruleset 0 is a valid ruleset, but when it's read in
351  * from the userland, it means "current ruleset for this mount-point".
352  */
353 static devfs_rid
354 devfs_rid_input(devfs_rid rid, struct devfs_mount *dm)
355 {
356 
357 	if (rid2rsn(rid) == 0)
358 		return (mkrid(dm->dm_ruleset, rid2rn(rid)));
359 	else
360 		return (rid);
361 }
362 
363 /*
364  * Apply dk to de and everything under de.
365  *
366  * XXX: This method needs a function call for every nested
367  * subdirectory in a devfs mount.  If we plan to have many of these,
368  * we might eventually run out of kernel stack space.
369  */
370 static void
371 devfs_rule_applyde_recursive(struct devfs_krule *dk, struct devfs_dirent *de)
372 {
373 	struct devfs_dirent *de2;
374 
375 	TAILQ_FOREACH(de2, &de->de_dlist, de_list)
376 		devfs_rule_applyde_recursive(dk, de2);
377 	devfs_rule_run(dk, de, devfs_rule_depth);
378 }
379 
380 /*
381  * Apply dk to all entires in dm.
382  */
383 static void
384 devfs_rule_applydm(struct devfs_krule *dk, struct devfs_mount *dm)
385 {
386 
387 	devfs_rule_applyde_recursive(dk, dm->dm_rootdir);
388 }
389 
390 /*
391  * Automatically select a number for a new rule in ds, and write the
392  * result into rnump.
393  */
394 static int
395 devfs_rule_autonumber(struct devfs_ruleset *ds, devfs_rnum *rnump)
396 {
397 	struct devfs_krule *dk;
398 
399 	/* Find the last rule. */
400 	SLIST_FOREACH(dk, &ds->ds_rules, dk_list) {
401 		if (SLIST_NEXT(dk, dk_list) == NULL)
402 			break;
403 	}
404 	if (dk == NULL)
405 		*rnump = 100;
406 	else {
407 		*rnump = rid2rn(dk->dk_rule.dr_id) + 100;
408 		/* Detect overflow. */
409 		if (*rnump < rid2rn(dk->dk_rule.dr_id))
410 			return (ERANGE);
411 	}
412 	KASSERT(devfs_rule_byid(mkrid(ds->ds_number, *rnump)) == NULL,
413 	    ("autonumbering resulted in an already existing rule"));
414 	return (0);
415 }
416 
417 /*
418  * Find a krule by id.
419  */
420 static struct devfs_krule *
421 devfs_rule_byid(devfs_rid rid)
422 {
423 	struct devfs_ruleset *ds;
424 	struct devfs_krule *dk;
425 	devfs_rnum rn;
426 
427 	rn = rid2rn(rid);
428 	ds = devfs_ruleset_bynum(rid2rsn(rid));
429 	if (ds == NULL)
430 		return (NULL);
431 	SLIST_FOREACH(dk, &ds->ds_rules, dk_list) {
432 		if (rid2rn(dk->dk_rule.dr_id) == rn)
433 			return (dk);
434 		else if (rid2rn(dk->dk_rule.dr_id) > rn)
435 			break;
436 	}
437 	return (NULL);
438 }
439 
440 /*
441  * Remove dkp from any lists it may be on and remove memory associated
442  * with it.
443  */
444 static int
445 devfs_rule_delete(struct devfs_krule **dkp)
446 {
447 	struct devfs_krule *dk = *dkp;
448 	struct devfs_ruleset *ds;
449 
450 	if (dk->dk_rule.dr_iacts & DRA_INCSET) {
451 		ds = devfs_ruleset_bynum(dk->dk_rule.dr_incset);
452 		KASSERT(ds != NULL, ("DRA_INCSET but bad dr_incset"));
453 		--ds->ds_refcount;
454 		devfs_ruleset_reap(&ds);
455 	}
456 	SLIST_REMOVE(&dk->dk_ruleset->ds_rules, dk, devfs_krule, dk_list);
457 	free(dk, M_DEVFS);
458 	*dkp = NULL;
459 	return (0);
460 }
461 
462 /*
463  * Get a struct cdev *corresponding to de so we can try to match rules based
464  * on it.  If this routine returns NULL, there is no struct cdev *associated
465  * with the dirent (symlinks and directories don't have dev_ts), and
466  * the caller should assume that any critera dependent on a dev_t
467  * don't match.
468  */
469 static struct cdev *
470 devfs_rule_getdev(struct devfs_dirent *de)
471 {
472 	struct cdev **devp, *dev;
473 
474 	devp = devfs_itod(de->de_inode);
475 	if (devp != NULL)
476 		dev = *devp;
477 	else
478 		dev = NULL;
479 	/* If we think this dirent should have a struct cdev *, alert the user. */
480 	if (dev == NULL && de->de_dirent->d_type != DT_LNK &&
481 	    de->de_dirent->d_type != DT_DIR)
482 		printf("Warning: no struct cdev *for %s\n", de->de_dirent->d_name);
483 	return (dev);
484 }
485 
486 /*
487  * Do what we need to do to a rule that we just loaded from the
488  * userland.  In particular, we need to check the magic, and adjust
489  * the ruleset appropriate if desired.
490  */
491 static int
492 devfs_rule_input(struct devfs_rule *dr, struct devfs_mount *dm)
493 {
494 
495 	if (dr->dr_magic != DEVFS_MAGIC)
496 		return (ERPCMISMATCH);
497 	dr->dr_id = devfs_rid_input(dr->dr_id, dm);
498 	return (0);
499 }
500 
501 /*
502  * Import dr into the appropriate place in the kernel (i.e., make a
503  * krule).  The value of dr is copied, so the pointer may be destroyed
504  * after this call completes.
505  */
506 static int
507 devfs_rule_insert(struct devfs_rule *dr)
508 {
509 	struct devfs_ruleset *ds, *dsi;
510 	struct devfs_krule *k1, *k2;
511 	struct devfs_krule *dk;
512 	devfs_rsnum rsnum;
513 	devfs_rnum dkrn;
514 	int error;
515 
516 	/*
517 	 * This stuff seems out of place here, but we want to do it as
518 	 * soon as possible so that if it fails, we don't have to roll
519 	 * back any changes we already made (e.g., ruleset creation).
520 	 */
521 	if (dr->dr_iacts & DRA_INCSET) {
522 		dsi = devfs_ruleset_bynum(dr->dr_incset);
523 		if (dsi == NULL)
524 			return (ESRCH);
525 	} else
526 		dsi = NULL;
527 
528 	rsnum = rid2rsn(dr->dr_id);
529 	ds = devfs_ruleset_bynum(rsnum);
530 	if (ds == NULL)
531 		ds = devfs_ruleset_create(rsnum);
532 	if (ds->ds_flags & DS_IMMUTABLE)
533 		return (EIO);
534 	dkrn = rid2rn(dr->dr_id);
535 	if (dkrn == 0) {
536 		error = devfs_rule_autonumber(ds, &dkrn);
537 		if (error != 0)
538 			return (error);
539 	}
540 
541 	dk = malloc(sizeof(*dk), M_DEVFS, M_WAITOK);
542 	dk->dk_ruleset = ds;
543 	if (dsi != NULL)
544 		++dsi->ds_refcount;
545 	/* XXX: Inspect dr? */
546 	memcpy(&dk->dk_rule, dr, sizeof(*dr));
547 	dk->dk_rule.dr_id = mkrid(rid2rsn(dk->dk_rule.dr_id), dkrn);
548 
549 	k1 = SLIST_FIRST(&ds->ds_rules);
550 	if (k1 == NULL || rid2rn(k1->dk_rule.dr_id) > dkrn)
551 		SLIST_INSERT_HEAD(&ds->ds_rules, dk, dk_list);
552 	else {
553 		SLIST_FOREACH(k1, &ds->ds_rules, dk_list) {
554 			k2 = SLIST_NEXT(k1, dk_list);
555 			if (k2 == NULL || rid2rn(k2->dk_rule.dr_id) > dkrn) {
556 				SLIST_INSERT_AFTER(k1, dk, dk_list);
557 				break;
558 			}
559 		}
560 	}
561 
562 	return (0);
563 }
564 
565 /*
566  * Determine whether dk matches de.  Returns 1 if dk should be run on
567  * de; 0, otherwise.
568  */
569 static int
570 devfs_rule_match(struct devfs_krule *dk, struct devfs_dirent *de)
571 {
572 	struct devfs_rule *dr = &dk->dk_rule;
573 	struct cdev *dev;
574 
575 	dev = devfs_rule_getdev(de);
576 	/*
577 	 * At this point, if dev is NULL, we should assume that any
578 	 * criteria that depend on it don't match.  We should *not*
579 	 * just ignore them (i.e., act like they weren't specified),
580 	 * since that makes a rule that only has criteria dependent on
581 	 * the struct cdev *match all symlinks and directories.
582 	 *
583 	 * Note also that the following tests are somewhat reversed:
584 	 * They're actually testing to see whether the condition does
585 	 * *not* match, since the default is to assume the rule should
586 	 * be run (such as if there are no conditions).
587 	 *
588 	 * XXX: lacks threadref on dev
589 	 */
590 	if (dr->dr_icond & DRC_DSWFLAGS)
591 		if (dev == NULL ||
592 		    (dev->si_devsw->d_flags & dr->dr_dswflags) == 0)
593 			return (0);
594 	if (dr->dr_icond & DRC_PATHPTRN)
595 		if (!devfs_rule_matchpath(dk, de))
596 			return (0);
597 
598 	return (1);
599 }
600 
601 /*
602  * Determine whether dk matches de on account of dr_pathptrn.
603  */
604 static int
605 devfs_rule_matchpath(struct devfs_krule *dk, struct devfs_dirent *de)
606 {
607 	struct devfs_rule *dr = &dk->dk_rule;
608 	char *pname;
609 	struct cdev *dev;
610 
611 	dev = devfs_rule_getdev(de);
612 	if (dev != NULL)
613 		pname = dev->si_name;
614 	else if (de->de_dirent->d_type == DT_LNK ||
615 	    de->de_dirent->d_type == DT_DIR)
616 		pname = de->de_dirent->d_name;
617 	else
618 		return (0);
619 	KASSERT(pname != NULL, ("devfs_rule_matchpath: NULL pname"));
620 
621 	return (fnmatch(dr->dr_pathptrn, pname, 0) == 0);
622 }
623 
624 /*
625  * Run dk on de.
626  */
627 static void
628 devfs_rule_run(struct devfs_krule *dk, struct devfs_dirent *de, unsigned depth)
629 {
630 	struct devfs_rule *dr = &dk->dk_rule;
631 	struct devfs_ruleset *ds;
632 
633 	if (!devfs_rule_match(dk, de))
634 		return;
635 	if (dr->dr_iacts & DRA_BACTS) {
636 		if (dr->dr_bacts & DRB_HIDE)
637 			de->de_flags |= DE_WHITEOUT;
638 		if (dr->dr_bacts & DRB_UNHIDE)
639 			de->de_flags &= ~DE_WHITEOUT;
640 	}
641 	if (dr->dr_iacts & DRA_UID)
642 		de->de_uid = dr->dr_uid;
643 	if (dr->dr_iacts & DRA_GID)
644 		de->de_gid = dr->dr_gid;
645 	if (dr->dr_iacts & DRA_MODE)
646 		de->de_mode = dr->dr_mode;
647 	if (dr->dr_iacts & DRA_INCSET) {
648 		/*
649 		 * XXX: we should tell the user if the depth is exceeded here
650 		 * XXX: but it is not obvious how to.  A return value will
651 		 * XXX: not work as this is called when devices are created
652 		 * XXX: long time after the rules were instantiated.
653 		 * XXX: a printf() would probably give too much noise, or
654 		 * XXX: DoS the machine.  I guess a a rate-limited message
655 		 * XXX: might work.
656 		 */
657 		if (depth > 0) {
658 			ds = devfs_ruleset_bynum(dk->dk_rule.dr_incset);
659 			KASSERT(ds != NULL, ("DRA_INCSET but bad dr_incset"));
660 			devfs_ruleset_applyde(ds, de, depth - 1);
661 		}
662 	}
663 }
664 
665 /*
666  * Apply all the rules in ds to de.
667  */
668 static void
669 devfs_ruleset_applyde(struct devfs_ruleset *ds, struct devfs_dirent *de, unsigned depth)
670 {
671 	struct devfs_krule *dk;
672 
673 	SLIST_FOREACH(dk, &ds->ds_rules, dk_list)
674 		devfs_rule_run(dk, de, depth);
675 }
676 
677 /*
678  * Apply all the rules in ds to all the entires in dm.
679  */
680 static void
681 devfs_ruleset_applydm(struct devfs_ruleset *ds, struct devfs_mount *dm)
682 {
683 	struct devfs_krule *dk;
684 
685 	/*
686 	 * XXX: Does it matter whether we do
687 	 *
688 	 *	foreach(dk in ds)
689 	 *		foreach(de in dm)
690 	 *			apply(dk to de)
691 	 *
692 	 * as opposed to
693 	 *
694 	 *	foreach(de in dm)
695 	 *		foreach(dk in ds)
696 	 *			apply(dk to de)
697 	 *
698 	 * The end result is obviously the same, but does the order
699 	 * matter?
700 	 */
701 	SLIST_FOREACH(dk, &ds->ds_rules, dk_list) {
702 		devfs_rule_applydm(dk, dm);
703 	}
704 }
705 
706 /*
707  * Find a ruleset by number.
708  */
709 static struct devfs_ruleset *
710 devfs_ruleset_bynum(devfs_rsnum rsnum)
711 {
712 	struct devfs_ruleset *ds;
713 
714 	SLIST_FOREACH(ds, &devfs_rulesets, ds_list) {
715 		if (ds->ds_number == rsnum)
716 			return (ds);
717 	}
718 	return (NULL);
719 }
720 
721 /*
722  * Create a new ruleset.
723  */
724 static struct devfs_ruleset *
725 devfs_ruleset_create(devfs_rsnum rsnum)
726 {
727 	struct devfs_ruleset *s1, *s2;
728 	struct devfs_ruleset *ds;
729 
730 	KASSERT(devfs_ruleset_bynum(rsnum) == NULL,
731 	    ("creating already existent ruleset %d", rsnum));
732 
733 	ds = malloc(sizeof(*ds), M_DEVFS, M_WAITOK | M_ZERO);
734 	ds->ds_number = rsnum;
735 	ds->ds_refcount = ds->ds_flags = 0;
736 	SLIST_INIT(&ds->ds_rules);
737 
738 	s1 = SLIST_FIRST(&devfs_rulesets);
739 	if (s1 == NULL || s1->ds_number > rsnum)
740 		SLIST_INSERT_HEAD(&devfs_rulesets, ds, ds_list);
741 	else {
742 		SLIST_FOREACH(s1, &devfs_rulesets, ds_list) {
743 			s2 = SLIST_NEXT(s1, ds_list);
744 			if (s2 == NULL || s2->ds_number > rsnum) {
745 				SLIST_INSERT_AFTER(s1, ds, ds_list);
746 				break;
747 			}
748 		}
749 	}
750 
751 	return (ds);
752 }
753 
754 /*
755  * Remove a ruleset form the system.  The ruleset specified must be
756  * empty and not in use.
757  */
758 static void
759 devfs_ruleset_destroy(struct devfs_ruleset **dsp)
760 {
761 	struct devfs_ruleset *ds = *dsp;
762 
763 	KASSERT(SLIST_EMPTY(&ds->ds_rules), ("destroying non-empty ruleset"));
764 	KASSERT(ds->ds_refcount == 0, ("destroying busy ruleset"));
765 	KASSERT((ds->ds_flags & DS_IMMUTABLE) == 0,
766 	    ("destroying immutable ruleset"));
767 
768 	SLIST_REMOVE(&devfs_rulesets, ds, devfs_ruleset, ds_list);
769 	free(ds, M_DEVFS);
770 	*dsp = NULL;
771 }
772 
773 /*
774  * Remove a ruleset from the system if it's empty and not used
775  * anywhere.  This should be called after every time a rule is deleted
776  * from this ruleset or the reference count is decremented.
777  */
778 static void
779 devfs_ruleset_reap(struct devfs_ruleset **dsp)
780 {
781 	struct devfs_ruleset *ds = *dsp;
782 
783 	if (SLIST_EMPTY(&ds->ds_rules) && ds->ds_refcount == 0) {
784 		devfs_ruleset_destroy(&ds);
785 		*dsp = ds;
786 	}
787 }
788 
789 /*
790  * Make rsnum the active ruleset for dm.
791  */
792 static int
793 devfs_ruleset_use(devfs_rsnum rsnum, struct devfs_mount *dm)
794 {
795 	struct devfs_ruleset *cds, *ds;
796 
797 	ds = devfs_ruleset_bynum(rsnum);
798 	if (ds == NULL)
799 		ds = devfs_ruleset_create(rsnum);
800 	cds = devfs_ruleset_bynum(dm->dm_ruleset);
801 	KASSERT(cds != NULL, ("mount-point has NULL ruleset"));
802 
803 	/* These should probably be made atomic somehow. */
804 	--cds->ds_refcount;
805 	++ds->ds_refcount;
806 	dm->dm_ruleset = rsnum;
807 
808 	devfs_ruleset_reap(&cds);
809 	return (0);
810 }
811