]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/udev/udev-rules.c
62db0016ebdde4c6f7406739545faae72d98412a
[thirdparty/systemd.git] / src / udev / udev-rules.c
1 /*
2 * Copyright (C) 2003-2012 Kay Sievers <kay@vrfy.org>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <ctype.h>
19 #include <dirent.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <fnmatch.h>
23 #include <limits.h>
24 #include <stdbool.h>
25 #include <stddef.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <time.h>
30 #include <unistd.h>
31
32 #include "conf-files.h"
33 #include "escape.h"
34 #include "path-util.h"
35 #include "strbuf.h"
36 #include "strv.h"
37 #include "sysctl-util.h"
38 #include "util.h"
39 #include "udev.h"
40
41 #define PREALLOC_TOKEN 2048
42
43 struct uid_gid {
44 unsigned int name_off;
45 union {
46 uid_t uid;
47 gid_t gid;
48 };
49 };
50
51 static const char* const rules_dirs[] = {
52 "/etc/udev/rules.d",
53 "/run/udev/rules.d",
54 UDEVLIBEXECDIR "/rules.d",
55 NULL
56 };
57
58 struct udev_rules {
59 struct udev *udev;
60 usec_t dirs_ts_usec;
61 int resolve_names;
62
63 /* every key in the rules file becomes a token */
64 struct token *tokens;
65 unsigned int token_cur;
66 unsigned int token_max;
67
68 /* all key strings are copied and de-duplicated in a single continuous string buffer */
69 struct strbuf *strbuf;
70
71 /* during rule parsing, uid/gid lookup results are cached */
72 struct uid_gid *uids;
73 unsigned int uids_cur;
74 unsigned int uids_max;
75 struct uid_gid *gids;
76 unsigned int gids_cur;
77 unsigned int gids_max;
78 };
79
80 static char *rules_str(struct udev_rules *rules, unsigned int off) {
81 return rules->strbuf->buf + off;
82 }
83
84 static unsigned int rules_add_string(struct udev_rules *rules, const char *s) {
85 return strbuf_add_string(rules->strbuf, s, strlen(s));
86 }
87
88 /* KEY=="", KEY!="", KEY+="", KEY-="", KEY="", KEY:="" */
89 enum operation_type {
90 OP_UNSET,
91
92 OP_MATCH,
93 OP_NOMATCH,
94 OP_MATCH_MAX,
95
96 OP_ADD,
97 OP_REMOVE,
98 OP_ASSIGN,
99 OP_ASSIGN_FINAL,
100 };
101
102 enum string_glob_type {
103 GL_UNSET,
104 GL_PLAIN, /* no special chars */
105 GL_GLOB, /* shell globs ?,*,[] */
106 GL_SPLIT, /* multi-value A|B */
107 GL_SPLIT_GLOB, /* multi-value with glob A*|B* */
108 GL_SOMETHING, /* commonly used "?*" */
109 };
110
111 enum string_subst_type {
112 SB_UNSET,
113 SB_NONE,
114 SB_FORMAT,
115 SB_SUBSYS,
116 };
117
118 /* tokens of a rule are sorted/handled in this order */
119 enum token_type {
120 TK_UNSET,
121 TK_RULE,
122
123 TK_M_ACTION, /* val */
124 TK_M_DEVPATH, /* val */
125 TK_M_KERNEL, /* val */
126 TK_M_DEVLINK, /* val */
127 TK_M_NAME, /* val */
128 TK_M_ENV, /* val, attr */
129 TK_M_TAG, /* val */
130 TK_M_SUBSYSTEM, /* val */
131 TK_M_DRIVER, /* val */
132 TK_M_WAITFOR, /* val */
133 TK_M_ATTR, /* val, attr */
134 TK_M_SYSCTL, /* val, attr */
135
136 TK_M_PARENTS_MIN,
137 TK_M_KERNELS, /* val */
138 TK_M_SUBSYSTEMS, /* val */
139 TK_M_DRIVERS, /* val */
140 TK_M_ATTRS, /* val, attr */
141 TK_M_TAGS, /* val */
142 TK_M_PARENTS_MAX,
143
144 TK_M_TEST, /* val, mode_t */
145 TK_M_PROGRAM, /* val */
146 TK_M_IMPORT_FILE, /* val */
147 TK_M_IMPORT_PROG, /* val */
148 TK_M_IMPORT_BUILTIN, /* val */
149 TK_M_IMPORT_DB, /* val */
150 TK_M_IMPORT_CMDLINE, /* val */
151 TK_M_IMPORT_PARENT, /* val */
152 TK_M_RESULT, /* val */
153 TK_M_MAX,
154
155 TK_A_STRING_ESCAPE_NONE,
156 TK_A_STRING_ESCAPE_REPLACE,
157 TK_A_DB_PERSIST,
158 TK_A_INOTIFY_WATCH, /* int */
159 TK_A_DEVLINK_PRIO, /* int */
160 TK_A_OWNER, /* val */
161 TK_A_GROUP, /* val */
162 TK_A_MODE, /* val */
163 TK_A_OWNER_ID, /* uid_t */
164 TK_A_GROUP_ID, /* gid_t */
165 TK_A_MODE_ID, /* mode_t */
166 TK_A_TAG, /* val */
167 TK_A_STATIC_NODE, /* val */
168 TK_A_SECLABEL, /* val, attr */
169 TK_A_ENV, /* val, attr */
170 TK_A_NAME, /* val */
171 TK_A_DEVLINK, /* val */
172 TK_A_ATTR, /* val, attr */
173 TK_A_SYSCTL, /* val, attr */
174 TK_A_RUN_BUILTIN, /* val, bool */
175 TK_A_RUN_PROGRAM, /* val, bool */
176 TK_A_GOTO, /* size_t */
177
178 TK_END,
179 };
180
181 /* we try to pack stuff in a way that we take only 12 bytes per token */
182 struct token {
183 union {
184 unsigned char type; /* same in rule and key */
185 struct {
186 enum token_type type:8;
187 bool can_set_name:1;
188 bool has_static_node:1;
189 unsigned int unused:6;
190 unsigned short token_count;
191 unsigned int label_off;
192 unsigned short filename_off;
193 unsigned short filename_line;
194 } rule;
195 struct {
196 enum token_type type:8;
197 enum operation_type op:8;
198 enum string_glob_type glob:8;
199 enum string_subst_type subst:4;
200 enum string_subst_type attrsubst:4;
201 unsigned int value_off;
202 union {
203 unsigned int attr_off;
204 unsigned int rule_goto;
205 mode_t mode;
206 uid_t uid;
207 gid_t gid;
208 int devlink_prio;
209 int watch;
210 enum udev_builtin_cmd builtin_cmd;
211 };
212 } key;
213 };
214 };
215
216 #define MAX_TK 64
217 struct rule_tmp {
218 struct udev_rules *rules;
219 struct token rule;
220 struct token token[MAX_TK];
221 unsigned int token_cur;
222 };
223
224 #ifdef DEBUG
225 static const char *operation_str(enum operation_type type) {
226 static const char *operation_strs[] = {
227 [OP_UNSET] = "UNSET",
228 [OP_MATCH] = "match",
229 [OP_NOMATCH] = "nomatch",
230 [OP_MATCH_MAX] = "MATCH_MAX",
231
232 [OP_ADD] = "add",
233 [OP_REMOVE] = "remove",
234 [OP_ASSIGN] = "assign",
235 [OP_ASSIGN_FINAL] = "assign-final",
236 } ;
237
238 return operation_strs[type];
239 }
240
241 static const char *string_glob_str(enum string_glob_type type) {
242 static const char *string_glob_strs[] = {
243 [GL_UNSET] = "UNSET",
244 [GL_PLAIN] = "plain",
245 [GL_GLOB] = "glob",
246 [GL_SPLIT] = "split",
247 [GL_SPLIT_GLOB] = "split-glob",
248 [GL_SOMETHING] = "split-glob",
249 };
250
251 return string_glob_strs[type];
252 }
253
254 static const char *token_str(enum token_type type) {
255 static const char *token_strs[] = {
256 [TK_UNSET] = "UNSET",
257 [TK_RULE] = "RULE",
258
259 [TK_M_ACTION] = "M ACTION",
260 [TK_M_DEVPATH] = "M DEVPATH",
261 [TK_M_KERNEL] = "M KERNEL",
262 [TK_M_DEVLINK] = "M DEVLINK",
263 [TK_M_NAME] = "M NAME",
264 [TK_M_ENV] = "M ENV",
265 [TK_M_TAG] = "M TAG",
266 [TK_M_SUBSYSTEM] = "M SUBSYSTEM",
267 [TK_M_DRIVER] = "M DRIVER",
268 [TK_M_WAITFOR] = "M WAITFOR",
269 [TK_M_ATTR] = "M ATTR",
270 [TK_M_SYSCTL] = "M SYSCTL",
271
272 [TK_M_PARENTS_MIN] = "M PARENTS_MIN",
273 [TK_M_KERNELS] = "M KERNELS",
274 [TK_M_SUBSYSTEMS] = "M SUBSYSTEMS",
275 [TK_M_DRIVERS] = "M DRIVERS",
276 [TK_M_ATTRS] = "M ATTRS",
277 [TK_M_TAGS] = "M TAGS",
278 [TK_M_PARENTS_MAX] = "M PARENTS_MAX",
279
280 [TK_M_TEST] = "M TEST",
281 [TK_M_PROGRAM] = "M PROGRAM",
282 [TK_M_IMPORT_FILE] = "M IMPORT_FILE",
283 [TK_M_IMPORT_PROG] = "M IMPORT_PROG",
284 [TK_M_IMPORT_BUILTIN] = "M IMPORT_BUILTIN",
285 [TK_M_IMPORT_DB] = "M IMPORT_DB",
286 [TK_M_IMPORT_CMDLINE] = "M IMPORT_CMDLINE",
287 [TK_M_IMPORT_PARENT] = "M IMPORT_PARENT",
288 [TK_M_RESULT] = "M RESULT",
289 [TK_M_MAX] = "M MAX",
290
291 [TK_A_STRING_ESCAPE_NONE] = "A STRING_ESCAPE_NONE",
292 [TK_A_STRING_ESCAPE_REPLACE] = "A STRING_ESCAPE_REPLACE",
293 [TK_A_DB_PERSIST] = "A DB_PERSIST",
294 [TK_A_INOTIFY_WATCH] = "A INOTIFY_WATCH",
295 [TK_A_DEVLINK_PRIO] = "A DEVLINK_PRIO",
296 [TK_A_OWNER] = "A OWNER",
297 [TK_A_GROUP] = "A GROUP",
298 [TK_A_MODE] = "A MODE",
299 [TK_A_OWNER_ID] = "A OWNER_ID",
300 [TK_A_GROUP_ID] = "A GROUP_ID",
301 [TK_A_STATIC_NODE] = "A STATIC_NODE",
302 [TK_A_SECLABEL] = "A SECLABEL",
303 [TK_A_MODE_ID] = "A MODE_ID",
304 [TK_A_ENV] = "A ENV",
305 [TK_A_TAG] = "A ENV",
306 [TK_A_NAME] = "A NAME",
307 [TK_A_DEVLINK] = "A DEVLINK",
308 [TK_A_ATTR] = "A ATTR",
309 [TK_A_SYSCTL] = "A SYSCTL",
310 [TK_A_RUN_BUILTIN] = "A RUN_BUILTIN",
311 [TK_A_RUN_PROGRAM] = "A RUN_PROGRAM",
312 [TK_A_GOTO] = "A GOTO",
313
314 [TK_END] = "END",
315 };
316
317 return token_strs[type];
318 }
319
320 static void dump_token(struct udev_rules *rules, struct token *token) {
321 enum token_type type = token->type;
322 enum operation_type op = token->key.op;
323 enum string_glob_type glob = token->key.glob;
324 const char *value = str(rules, token->key.value_off);
325 const char *attr = &rules->buf[token->key.attr_off];
326
327 switch (type) {
328 case TK_RULE:
329 {
330 const char *tks_ptr = (char *)rules->tokens;
331 const char *tk_ptr = (char *)token;
332 unsigned int idx = (tk_ptr - tks_ptr) / sizeof(struct token);
333
334 log_debug("* RULE %s:%u, token: %u, count: %u, label: '%s'",
335 &rules->buf[token->rule.filename_off], token->rule.filename_line,
336 idx, token->rule.token_count,
337 &rules->buf[token->rule.label_off]);
338 break;
339 }
340 case TK_M_ACTION:
341 case TK_M_DEVPATH:
342 case TK_M_KERNEL:
343 case TK_M_SUBSYSTEM:
344 case TK_M_DRIVER:
345 case TK_M_WAITFOR:
346 case TK_M_DEVLINK:
347 case TK_M_NAME:
348 case TK_M_KERNELS:
349 case TK_M_SUBSYSTEMS:
350 case TK_M_DRIVERS:
351 case TK_M_TAGS:
352 case TK_M_PROGRAM:
353 case TK_M_IMPORT_FILE:
354 case TK_M_IMPORT_PROG:
355 case TK_M_IMPORT_DB:
356 case TK_M_IMPORT_CMDLINE:
357 case TK_M_IMPORT_PARENT:
358 case TK_M_RESULT:
359 case TK_A_NAME:
360 case TK_A_DEVLINK:
361 case TK_A_OWNER:
362 case TK_A_GROUP:
363 case TK_A_MODE:
364 case TK_A_RUN_BUILTIN:
365 case TK_A_RUN_PROGRAM:
366 log_debug("%s %s '%s'(%s)",
367 token_str(type), operation_str(op), value, string_glob_str(glob));
368 break;
369 case TK_M_IMPORT_BUILTIN:
370 log_debug("%s %i '%s'", token_str(type), token->key.builtin_cmd, value);
371 break;
372 case TK_M_ATTR:
373 case TK_M_SYSCTL:
374 case TK_M_ATTRS:
375 case TK_M_ENV:
376 case TK_A_ATTR:
377 case TK_A_SYSCTL:
378 case TK_A_ENV:
379 log_debug("%s %s '%s' '%s'(%s)",
380 token_str(type), operation_str(op), attr, value, string_glob_str(glob));
381 break;
382 case TK_M_TAG:
383 case TK_A_TAG:
384 log_debug("%s %s '%s'", token_str(type), operation_str(op), value);
385 break;
386 case TK_A_STRING_ESCAPE_NONE:
387 case TK_A_STRING_ESCAPE_REPLACE:
388 case TK_A_DB_PERSIST:
389 log_debug("%s", token_str(type));
390 break;
391 case TK_M_TEST:
392 log_debug("%s %s '%s'(%s) %#o",
393 token_str(type), operation_str(op), value, string_glob_str(glob), token->key.mode);
394 break;
395 case TK_A_INOTIFY_WATCH:
396 log_debug("%s %u", token_str(type), token->key.watch);
397 break;
398 case TK_A_DEVLINK_PRIO:
399 log_debug("%s %u", token_str(type), token->key.devlink_prio);
400 break;
401 case TK_A_OWNER_ID:
402 log_debug("%s %s %u", token_str(type), operation_str(op), token->key.uid);
403 break;
404 case TK_A_GROUP_ID:
405 log_debug("%s %s %u", token_str(type), operation_str(op), token->key.gid);
406 break;
407 case TK_A_MODE_ID:
408 log_debug("%s %s %#o", token_str(type), operation_str(op), token->key.mode);
409 break;
410 case TK_A_STATIC_NODE:
411 log_debug("%s '%s'", token_str(type), value);
412 break;
413 case TK_A_SECLABEL:
414 log_debug("%s %s '%s' '%s'", token_str(type), operation_str(op), attr, value);
415 break;
416 case TK_A_GOTO:
417 log_debug("%s '%s' %u", token_str(type), value, token->key.rule_goto);
418 break;
419 case TK_END:
420 log_debug("* %s", token_str(type));
421 break;
422 case TK_M_PARENTS_MIN:
423 case TK_M_PARENTS_MAX:
424 case TK_M_MAX:
425 case TK_UNSET:
426 log_debug("unknown type %u", type);
427 break;
428 }
429 }
430
431 static void dump_rules(struct udev_rules *rules) {
432 unsigned int i;
433
434 log_debug("dumping %u (%zu bytes) tokens, %u (%zu bytes) strings",
435 rules->token_cur,
436 rules->token_cur * sizeof(struct token),
437 rules->buf_count,
438 rules->buf_cur);
439 for (i = 0; i < rules->token_cur; i++)
440 dump_token(rules, &rules->tokens[i]);
441 }
442 #else
443 static inline void dump_token(struct udev_rules *rules, struct token *token) {}
444 static inline void dump_rules(struct udev_rules *rules) {}
445 #endif /* DEBUG */
446
447 static int add_token(struct udev_rules *rules, struct token *token) {
448 /* grow buffer if needed */
449 if (rules->token_cur+1 >= rules->token_max) {
450 struct token *tokens;
451 unsigned int add;
452
453 /* double the buffer size */
454 add = rules->token_max;
455 if (add < 8)
456 add = 8;
457
458 tokens = realloc(rules->tokens, (rules->token_max + add ) * sizeof(struct token));
459 if (tokens == NULL)
460 return -1;
461 rules->tokens = tokens;
462 rules->token_max += add;
463 }
464 memcpy(&rules->tokens[rules->token_cur], token, sizeof(struct token));
465 rules->token_cur++;
466 return 0;
467 }
468
469 static uid_t add_uid(struct udev_rules *rules, const char *owner) {
470 unsigned int i;
471 uid_t uid = 0;
472 unsigned int off;
473 int r;
474
475 /* lookup, if we know it already */
476 for (i = 0; i < rules->uids_cur; i++) {
477 off = rules->uids[i].name_off;
478 if (streq(rules_str(rules, off), owner)) {
479 uid = rules->uids[i].uid;
480 return uid;
481 }
482 }
483 r = get_user_creds(&owner, &uid, NULL, NULL, NULL);
484 if (r < 0) {
485 if (r == -ENOENT || r == -ESRCH)
486 log_error("specified user '%s' unknown", owner);
487 else
488 log_error_errno(r, "error resolving user '%s': %m", owner);
489 }
490
491 /* grow buffer if needed */
492 if (rules->uids_cur+1 >= rules->uids_max) {
493 struct uid_gid *uids;
494 unsigned int add;
495
496 /* double the buffer size */
497 add = rules->uids_max;
498 if (add < 1)
499 add = 8;
500
501 uids = realloc(rules->uids, (rules->uids_max + add ) * sizeof(struct uid_gid));
502 if (uids == NULL)
503 return uid;
504 rules->uids = uids;
505 rules->uids_max += add;
506 }
507 rules->uids[rules->uids_cur].uid = uid;
508 off = rules_add_string(rules, owner);
509 if (off <= 0)
510 return uid;
511 rules->uids[rules->uids_cur].name_off = off;
512 rules->uids_cur++;
513 return uid;
514 }
515
516 static gid_t add_gid(struct udev_rules *rules, const char *group) {
517 unsigned int i;
518 gid_t gid = 0;
519 unsigned int off;
520 int r;
521
522 /* lookup, if we know it already */
523 for (i = 0; i < rules->gids_cur; i++) {
524 off = rules->gids[i].name_off;
525 if (streq(rules_str(rules, off), group)) {
526 gid = rules->gids[i].gid;
527 return gid;
528 }
529 }
530 r = get_group_creds(&group, &gid);
531 if (r < 0) {
532 if (r == -ENOENT || r == -ESRCH)
533 log_error("specified group '%s' unknown", group);
534 else
535 log_error_errno(r, "error resolving group '%s': %m", group);
536 }
537
538 /* grow buffer if needed */
539 if (rules->gids_cur+1 >= rules->gids_max) {
540 struct uid_gid *gids;
541 unsigned int add;
542
543 /* double the buffer size */
544 add = rules->gids_max;
545 if (add < 1)
546 add = 8;
547
548 gids = realloc(rules->gids, (rules->gids_max + add ) * sizeof(struct uid_gid));
549 if (gids == NULL)
550 return gid;
551 rules->gids = gids;
552 rules->gids_max += add;
553 }
554 rules->gids[rules->gids_cur].gid = gid;
555 off = rules_add_string(rules, group);
556 if (off <= 0)
557 return gid;
558 rules->gids[rules->gids_cur].name_off = off;
559 rules->gids_cur++;
560 return gid;
561 }
562
563 static int import_property_from_string(struct udev_device *dev, char *line) {
564 char *key;
565 char *val;
566 size_t len;
567
568 /* find key */
569 key = line;
570 while (isspace(key[0]))
571 key++;
572
573 /* comment or empty line */
574 if (key[0] == '#' || key[0] == '\0')
575 return -1;
576
577 /* split key/value */
578 val = strchr(key, '=');
579 if (val == NULL)
580 return -1;
581 val[0] = '\0';
582 val++;
583
584 /* find value */
585 while (isspace(val[0]))
586 val++;
587
588 /* terminate key */
589 len = strlen(key);
590 if (len == 0)
591 return -1;
592 while (isspace(key[len-1]))
593 len--;
594 key[len] = '\0';
595
596 /* terminate value */
597 len = strlen(val);
598 if (len == 0)
599 return -1;
600 while (isspace(val[len-1]))
601 len--;
602 val[len] = '\0';
603
604 if (len == 0)
605 return -1;
606
607 /* unquote */
608 if (val[0] == '"' || val[0] == '\'') {
609 if (val[len-1] != val[0]) {
610 log_debug("inconsistent quoting: '%s', skip", line);
611 return -1;
612 }
613 val[len-1] = '\0';
614 val++;
615 }
616
617 udev_device_add_property(dev, key, val);
618
619 return 0;
620 }
621
622 static int import_file_into_properties(struct udev_device *dev, const char *filename) {
623 FILE *f;
624 char line[UTIL_LINE_SIZE];
625
626 f = fopen(filename, "re");
627 if (f == NULL)
628 return -1;
629 while (fgets(line, sizeof(line), f) != NULL)
630 import_property_from_string(dev, line);
631 fclose(f);
632 return 0;
633 }
634
635 static int import_program_into_properties(struct udev_event *event,
636 usec_t timeout_usec,
637 usec_t timeout_warn_usec,
638 const char *program) {
639 char result[UTIL_LINE_SIZE];
640 char *line;
641 int err;
642
643 err = udev_event_spawn(event, timeout_usec, timeout_warn_usec, true, program, result, sizeof(result));
644 if (err < 0)
645 return err;
646
647 line = result;
648 while (line != NULL) {
649 char *pos;
650
651 pos = strchr(line, '\n');
652 if (pos != NULL) {
653 pos[0] = '\0';
654 pos = &pos[1];
655 }
656 import_property_from_string(event->dev, line);
657 line = pos;
658 }
659 return 0;
660 }
661
662 static int import_parent_into_properties(struct udev_device *dev, const char *filter) {
663 struct udev_device *dev_parent;
664 struct udev_list_entry *list_entry;
665
666 assert(dev);
667 assert(filter);
668
669 dev_parent = udev_device_get_parent(dev);
670 if (dev_parent == NULL)
671 return -1;
672
673 udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(dev_parent)) {
674 const char *key = udev_list_entry_get_name(list_entry);
675 const char *val = udev_list_entry_get_value(list_entry);
676
677 if (fnmatch(filter, key, 0) == 0)
678 udev_device_add_property(dev, key, val);
679 }
680 return 0;
681 }
682
683 static int attr_subst_subdir(char *attr, size_t len) {
684 bool found = false;
685
686 if (strstr(attr, "/*/")) {
687 char *pos;
688 char dirname[UTIL_PATH_SIZE];
689 const char *tail;
690 DIR *dir;
691
692 strscpy(dirname, sizeof(dirname), attr);
693 pos = strstr(dirname, "/*/");
694 if (pos == NULL)
695 return -1;
696 pos[0] = '\0';
697 tail = &pos[2];
698 dir = opendir(dirname);
699 if (dir != NULL) {
700 struct dirent *dent;
701
702 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
703 struct stat stats;
704
705 if (dent->d_name[0] == '.')
706 continue;
707 strscpyl(attr, len, dirname, "/", dent->d_name, tail, NULL);
708 if (stat(attr, &stats) == 0) {
709 found = true;
710 break;
711 }
712 }
713 closedir(dir);
714 }
715 }
716
717 return found;
718 }
719
720 static int get_key(struct udev *udev, char **line, char **key, enum operation_type *op, char **value) {
721 char *linepos;
722 char *temp;
723
724 linepos = *line;
725 if (linepos == NULL || linepos[0] == '\0')
726 return -1;
727
728 /* skip whitespace */
729 while (isspace(linepos[0]) || linepos[0] == ',')
730 linepos++;
731
732 /* get the key */
733 if (linepos[0] == '\0')
734 return -1;
735 *key = linepos;
736
737 for (;;) {
738 linepos++;
739 if (linepos[0] == '\0')
740 return -1;
741 if (isspace(linepos[0]))
742 break;
743 if (linepos[0] == '=')
744 break;
745 if ((linepos[0] == '+') || (linepos[0] == '-') || (linepos[0] == '!') || (linepos[0] == ':'))
746 if (linepos[1] == '=')
747 break;
748 }
749
750 /* remember end of key */
751 temp = linepos;
752
753 /* skip whitespace after key */
754 while (isspace(linepos[0]))
755 linepos++;
756 if (linepos[0] == '\0')
757 return -1;
758
759 /* get operation type */
760 if (linepos[0] == '=' && linepos[1] == '=') {
761 *op = OP_MATCH;
762 linepos += 2;
763 } else if (linepos[0] == '!' && linepos[1] == '=') {
764 *op = OP_NOMATCH;
765 linepos += 2;
766 } else if (linepos[0] == '+' && linepos[1] == '=') {
767 *op = OP_ADD;
768 linepos += 2;
769 } else if (linepos[0] == '-' && linepos[1] == '=') {
770 *op = OP_REMOVE;
771 linepos += 2;
772 } else if (linepos[0] == '=') {
773 *op = OP_ASSIGN;
774 linepos++;
775 } else if (linepos[0] == ':' && linepos[1] == '=') {
776 *op = OP_ASSIGN_FINAL;
777 linepos += 2;
778 } else
779 return -1;
780
781 /* terminate key */
782 temp[0] = '\0';
783
784 /* skip whitespace after operator */
785 while (isspace(linepos[0]))
786 linepos++;
787 if (linepos[0] == '\0')
788 return -1;
789
790 /* get the value */
791 if (linepos[0] == '"')
792 linepos++;
793 else
794 return -1;
795 *value = linepos;
796
797 /* terminate */
798 temp = strchr(linepos, '"');
799 if (!temp)
800 return -1;
801 temp[0] = '\0';
802 temp++;
803
804 /* move line to next key */
805 *line = temp;
806 return 0;
807 }
808
809 /* extract possible KEY{attr} */
810 static const char *get_key_attribute(struct udev *udev, char *str) {
811 char *pos;
812 char *attr;
813
814 attr = strchr(str, '{');
815 if (attr != NULL) {
816 attr++;
817 pos = strchr(attr, '}');
818 if (pos == NULL) {
819 log_error("missing closing brace for format");
820 return NULL;
821 }
822 pos[0] = '\0';
823 return attr;
824 }
825 return NULL;
826 }
827
828 static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,
829 enum operation_type op,
830 const char *value, const void *data) {
831 struct token *token = &rule_tmp->token[rule_tmp->token_cur];
832 const char *attr = NULL;
833
834 memzero(token, sizeof(struct token));
835
836 switch (type) {
837 case TK_M_ACTION:
838 case TK_M_DEVPATH:
839 case TK_M_KERNEL:
840 case TK_M_SUBSYSTEM:
841 case TK_M_DRIVER:
842 case TK_M_WAITFOR:
843 case TK_M_DEVLINK:
844 case TK_M_NAME:
845 case TK_M_KERNELS:
846 case TK_M_SUBSYSTEMS:
847 case TK_M_DRIVERS:
848 case TK_M_TAGS:
849 case TK_M_PROGRAM:
850 case TK_M_IMPORT_FILE:
851 case TK_M_IMPORT_PROG:
852 case TK_M_IMPORT_DB:
853 case TK_M_IMPORT_CMDLINE:
854 case TK_M_IMPORT_PARENT:
855 case TK_M_RESULT:
856 case TK_A_OWNER:
857 case TK_A_GROUP:
858 case TK_A_MODE:
859 case TK_A_DEVLINK:
860 case TK_A_NAME:
861 case TK_A_GOTO:
862 case TK_M_TAG:
863 case TK_A_TAG:
864 case TK_A_STATIC_NODE:
865 token->key.value_off = rules_add_string(rule_tmp->rules, value);
866 break;
867 case TK_M_IMPORT_BUILTIN:
868 token->key.value_off = rules_add_string(rule_tmp->rules, value);
869 token->key.builtin_cmd = *(enum udev_builtin_cmd *)data;
870 break;
871 case TK_M_ENV:
872 case TK_M_ATTR:
873 case TK_M_SYSCTL:
874 case TK_M_ATTRS:
875 case TK_A_ATTR:
876 case TK_A_SYSCTL:
877 case TK_A_ENV:
878 case TK_A_SECLABEL:
879 attr = data;
880 token->key.value_off = rules_add_string(rule_tmp->rules, value);
881 token->key.attr_off = rules_add_string(rule_tmp->rules, attr);
882 break;
883 case TK_M_TEST:
884 token->key.value_off = rules_add_string(rule_tmp->rules, value);
885 if (data != NULL)
886 token->key.mode = *(mode_t *)data;
887 break;
888 case TK_A_STRING_ESCAPE_NONE:
889 case TK_A_STRING_ESCAPE_REPLACE:
890 case TK_A_DB_PERSIST:
891 break;
892 case TK_A_RUN_BUILTIN:
893 case TK_A_RUN_PROGRAM:
894 token->key.builtin_cmd = *(enum udev_builtin_cmd *)data;
895 token->key.value_off = rules_add_string(rule_tmp->rules, value);
896 break;
897 case TK_A_INOTIFY_WATCH:
898 case TK_A_DEVLINK_PRIO:
899 token->key.devlink_prio = *(int *)data;
900 break;
901 case TK_A_OWNER_ID:
902 token->key.uid = *(uid_t *)data;
903 break;
904 case TK_A_GROUP_ID:
905 token->key.gid = *(gid_t *)data;
906 break;
907 case TK_A_MODE_ID:
908 token->key.mode = *(mode_t *)data;
909 break;
910 case TK_RULE:
911 case TK_M_PARENTS_MIN:
912 case TK_M_PARENTS_MAX:
913 case TK_M_MAX:
914 case TK_END:
915 case TK_UNSET:
916 log_error("wrong type %u", type);
917 return -1;
918 }
919
920 if (value != NULL && type < TK_M_MAX) {
921 /* check if we need to split or call fnmatch() while matching rules */
922 enum string_glob_type glob;
923 int has_split;
924 int has_glob;
925
926 has_split = (strchr(value, '|') != NULL);
927 has_glob = string_is_glob(value);
928 if (has_split && has_glob) {
929 glob = GL_SPLIT_GLOB;
930 } else if (has_split) {
931 glob = GL_SPLIT;
932 } else if (has_glob) {
933 if (streq(value, "?*"))
934 glob = GL_SOMETHING;
935 else
936 glob = GL_GLOB;
937 } else {
938 glob = GL_PLAIN;
939 }
940 token->key.glob = glob;
941 }
942
943 if (value != NULL && type > TK_M_MAX) {
944 /* check if assigned value has substitution chars */
945 if (value[0] == '[')
946 token->key.subst = SB_SUBSYS;
947 else if (strchr(value, '%') != NULL || strchr(value, '$') != NULL)
948 token->key.subst = SB_FORMAT;
949 else
950 token->key.subst = SB_NONE;
951 }
952
953 if (attr != NULL) {
954 /* check if property/attribute name has substitution chars */
955 if (attr[0] == '[')
956 token->key.attrsubst = SB_SUBSYS;
957 else if (strchr(attr, '%') != NULL || strchr(attr, '$') != NULL)
958 token->key.attrsubst = SB_FORMAT;
959 else
960 token->key.attrsubst = SB_NONE;
961 }
962
963 token->key.type = type;
964 token->key.op = op;
965 rule_tmp->token_cur++;
966 if (rule_tmp->token_cur >= ELEMENTSOF(rule_tmp->token)) {
967 log_error("temporary rule array too small");
968 return -1;
969 }
970 return 0;
971 }
972
973 static int sort_token(struct udev_rules *rules, struct rule_tmp *rule_tmp) {
974 unsigned int i;
975 unsigned int start = 0;
976 unsigned int end = rule_tmp->token_cur;
977
978 for (i = 0; i < rule_tmp->token_cur; i++) {
979 enum token_type next_val = TK_UNSET;
980 unsigned int next_idx = 0;
981 unsigned int j;
982
983 /* find smallest value */
984 for (j = start; j < end; j++) {
985 if (rule_tmp->token[j].type == TK_UNSET)
986 continue;
987 if (next_val == TK_UNSET || rule_tmp->token[j].type < next_val) {
988 next_val = rule_tmp->token[j].type;
989 next_idx = j;
990 }
991 }
992
993 /* add token and mark done */
994 if (add_token(rules, &rule_tmp->token[next_idx]) != 0)
995 return -1;
996 rule_tmp->token[next_idx].type = TK_UNSET;
997
998 /* shrink range */
999 if (next_idx == start)
1000 start++;
1001 if (next_idx+1 == end)
1002 end--;
1003 }
1004 return 0;
1005 }
1006
1007 static int add_rule(struct udev_rules *rules, char *line,
1008 const char *filename, unsigned int filename_off, unsigned int lineno) {
1009 char *linepos;
1010 const char *attr;
1011 struct rule_tmp rule_tmp = {
1012 .rules = rules,
1013 .rule.type = TK_RULE,
1014 };
1015
1016 /* the offset in the rule is limited to unsigned short */
1017 if (filename_off < USHRT_MAX)
1018 rule_tmp.rule.rule.filename_off = filename_off;
1019 rule_tmp.rule.rule.filename_line = lineno;
1020
1021 linepos = line;
1022 for (;;) {
1023 char *key;
1024 char *value;
1025 enum operation_type op;
1026
1027 if (get_key(rules->udev, &linepos, &key, &op, &value) != 0) {
1028 /* Avoid erroring on trailing whitespace. This is probably rare
1029 * so save the work for the error case instead of always trying
1030 * to strip the trailing whitespace with strstrip(). */
1031 while (isblank(*linepos))
1032 linepos++;
1033
1034 /* If we aren't at the end of the line, this is a parsing error.
1035 * Make a best effort to describe where the problem is. */
1036 if (!strchr(NEWLINE, *linepos)) {
1037 char buf[2] = {*linepos};
1038 _cleanup_free_ char *tmp;
1039
1040 tmp = cescape(buf);
1041 log_error("invalid key/value pair in file %s on line %u, starting at character %tu ('%s')",
1042 filename, lineno, linepos - line + 1, tmp);
1043 if (*linepos == '#')
1044 log_error("hint: comments can only start at beginning of line");
1045 }
1046 break;
1047 }
1048
1049 if (streq(key, "ACTION")) {
1050 if (op > OP_MATCH_MAX) {
1051 log_error("invalid ACTION operation");
1052 goto invalid;
1053 }
1054 rule_add_key(&rule_tmp, TK_M_ACTION, op, value, NULL);
1055 continue;
1056 }
1057
1058 if (streq(key, "DEVPATH")) {
1059 if (op > OP_MATCH_MAX) {
1060 log_error("invalid DEVPATH operation");
1061 goto invalid;
1062 }
1063 rule_add_key(&rule_tmp, TK_M_DEVPATH, op, value, NULL);
1064 continue;
1065 }
1066
1067 if (streq(key, "KERNEL")) {
1068 if (op > OP_MATCH_MAX) {
1069 log_error("invalid KERNEL operation");
1070 goto invalid;
1071 }
1072 rule_add_key(&rule_tmp, TK_M_KERNEL, op, value, NULL);
1073 continue;
1074 }
1075
1076 if (streq(key, "SUBSYSTEM")) {
1077 if (op > OP_MATCH_MAX) {
1078 log_error("invalid SUBSYSTEM operation");
1079 goto invalid;
1080 }
1081 /* bus, class, subsystem events should all be the same */
1082 if (streq(value, "subsystem") ||
1083 streq(value, "bus") ||
1084 streq(value, "class")) {
1085 if (streq(value, "bus") || streq(value, "class"))
1086 log_error("'%s' must be specified as 'subsystem' "
1087 "please fix it in %s:%u", value, filename, lineno);
1088 rule_add_key(&rule_tmp, TK_M_SUBSYSTEM, op, "subsystem|class|bus", NULL);
1089 } else
1090 rule_add_key(&rule_tmp, TK_M_SUBSYSTEM, op, value, NULL);
1091 continue;
1092 }
1093
1094 if (streq(key, "DRIVER")) {
1095 if (op > OP_MATCH_MAX) {
1096 log_error("invalid DRIVER operation");
1097 goto invalid;
1098 }
1099 rule_add_key(&rule_tmp, TK_M_DRIVER, op, value, NULL);
1100 continue;
1101 }
1102
1103 if (startswith(key, "ATTR{")) {
1104 attr = get_key_attribute(rules->udev, key + strlen("ATTR"));
1105 if (attr == NULL) {
1106 log_error("error parsing ATTR attribute");
1107 goto invalid;
1108 }
1109 if (op == OP_REMOVE) {
1110 log_error("invalid ATTR operation");
1111 goto invalid;
1112 }
1113 if (op < OP_MATCH_MAX)
1114 rule_add_key(&rule_tmp, TK_M_ATTR, op, value, attr);
1115 else
1116 rule_add_key(&rule_tmp, TK_A_ATTR, op, value, attr);
1117 continue;
1118 }
1119
1120 if (startswith(key, "SYSCTL{")) {
1121 attr = get_key_attribute(rules->udev, key + strlen("SYSCTL"));
1122 if (attr == NULL) {
1123 log_error("error parsing SYSCTL attribute");
1124 goto invalid;
1125 }
1126 if (op == OP_REMOVE) {
1127 log_error("invalid SYSCTL operation");
1128 goto invalid;
1129 }
1130 if (op < OP_MATCH_MAX)
1131 rule_add_key(&rule_tmp, TK_M_SYSCTL, op, value, attr);
1132 else
1133 rule_add_key(&rule_tmp, TK_A_SYSCTL, op, value, attr);
1134 continue;
1135 }
1136
1137 if (startswith(key, "SECLABEL{")) {
1138 attr = get_key_attribute(rules->udev, key + strlen("SECLABEL"));
1139 if (!attr) {
1140 log_error("error parsing SECLABEL attribute");
1141 goto invalid;
1142 }
1143 if (op == OP_REMOVE) {
1144 log_error("invalid SECLABEL operation");
1145 goto invalid;
1146 }
1147
1148 rule_add_key(&rule_tmp, TK_A_SECLABEL, op, value, attr);
1149 continue;
1150 }
1151
1152 if (streq(key, "KERNELS")) {
1153 if (op > OP_MATCH_MAX) {
1154 log_error("invalid KERNELS operation");
1155 goto invalid;
1156 }
1157 rule_add_key(&rule_tmp, TK_M_KERNELS, op, value, NULL);
1158 continue;
1159 }
1160
1161 if (streq(key, "SUBSYSTEMS")) {
1162 if (op > OP_MATCH_MAX) {
1163 log_error("invalid SUBSYSTEMS operation");
1164 goto invalid;
1165 }
1166 rule_add_key(&rule_tmp, TK_M_SUBSYSTEMS, op, value, NULL);
1167 continue;
1168 }
1169
1170 if (streq(key, "DRIVERS")) {
1171 if (op > OP_MATCH_MAX) {
1172 log_error("invalid DRIVERS operation");
1173 goto invalid;
1174 }
1175 rule_add_key(&rule_tmp, TK_M_DRIVERS, op, value, NULL);
1176 continue;
1177 }
1178
1179 if (startswith(key, "ATTRS{")) {
1180 if (op > OP_MATCH_MAX) {
1181 log_error("invalid ATTRS operation");
1182 goto invalid;
1183 }
1184 attr = get_key_attribute(rules->udev, key + strlen("ATTRS"));
1185 if (attr == NULL) {
1186 log_error("error parsing ATTRS attribute");
1187 goto invalid;
1188 }
1189 if (startswith(attr, "device/"))
1190 log_error("the 'device' link may not be available in a future kernel, "
1191 "please fix it in %s:%u", filename, lineno);
1192 else if (strstr(attr, "../") != NULL)
1193 log_error("do not reference parent sysfs directories directly, "
1194 "it may break with a future kernel, please fix it in %s:%u", filename, lineno);
1195 rule_add_key(&rule_tmp, TK_M_ATTRS, op, value, attr);
1196 continue;
1197 }
1198
1199 if (streq(key, "TAGS")) {
1200 if (op > OP_MATCH_MAX) {
1201 log_error("invalid TAGS operation");
1202 goto invalid;
1203 }
1204 rule_add_key(&rule_tmp, TK_M_TAGS, op, value, NULL);
1205 continue;
1206 }
1207
1208 if (startswith(key, "ENV{")) {
1209 attr = get_key_attribute(rules->udev, key + strlen("ENV"));
1210 if (attr == NULL) {
1211 log_error("error parsing ENV attribute");
1212 goto invalid;
1213 }
1214 if (op == OP_REMOVE) {
1215 log_error("invalid ENV operation");
1216 goto invalid;
1217 }
1218 if (op < OP_MATCH_MAX) {
1219 if (rule_add_key(&rule_tmp, TK_M_ENV, op, value, attr) != 0)
1220 goto invalid;
1221 } else {
1222 static const char *blacklist[] = {
1223 "ACTION",
1224 "SUBSYSTEM",
1225 "DEVTYPE",
1226 "MAJOR",
1227 "MINOR",
1228 "DRIVER",
1229 "IFINDEX",
1230 "DEVNAME",
1231 "DEVLINKS",
1232 "DEVPATH",
1233 "TAGS",
1234 };
1235 unsigned int i;
1236
1237 for (i = 0; i < ELEMENTSOF(blacklist); i++) {
1238 if (!streq(attr, blacklist[i]))
1239 continue;
1240 log_error("invalid ENV attribute, '%s' can not be set %s:%u", attr, filename, lineno);
1241 goto invalid;
1242 }
1243 if (rule_add_key(&rule_tmp, TK_A_ENV, op, value, attr) != 0)
1244 goto invalid;
1245 }
1246 continue;
1247 }
1248
1249 if (streq(key, "TAG")) {
1250 if (op < OP_MATCH_MAX)
1251 rule_add_key(&rule_tmp, TK_M_TAG, op, value, NULL);
1252 else
1253 rule_add_key(&rule_tmp, TK_A_TAG, op, value, NULL);
1254 continue;
1255 }
1256
1257 if (streq(key, "PROGRAM")) {
1258 if (op == OP_REMOVE) {
1259 log_error("invalid PROGRAM operation");
1260 goto invalid;
1261 }
1262 rule_add_key(&rule_tmp, TK_M_PROGRAM, op, value, NULL);
1263 continue;
1264 }
1265
1266 if (streq(key, "RESULT")) {
1267 if (op > OP_MATCH_MAX) {
1268 log_error("invalid RESULT operation");
1269 goto invalid;
1270 }
1271 rule_add_key(&rule_tmp, TK_M_RESULT, op, value, NULL);
1272 continue;
1273 }
1274
1275 if (startswith(key, "IMPORT")) {
1276 attr = get_key_attribute(rules->udev, key + strlen("IMPORT"));
1277 if (attr == NULL) {
1278 log_error("IMPORT{} type missing, ignoring IMPORT %s:%u", filename, lineno);
1279 continue;
1280 }
1281 if (op == OP_REMOVE) {
1282 log_error("invalid IMPORT operation");
1283 goto invalid;
1284 }
1285 if (streq(attr, "program")) {
1286 /* find known built-in command */
1287 if (value[0] != '/') {
1288 enum udev_builtin_cmd cmd;
1289
1290 cmd = udev_builtin_lookup(value);
1291 if (cmd < UDEV_BUILTIN_MAX) {
1292 log_debug("IMPORT found builtin '%s', replacing %s:%u",
1293 value, filename, lineno);
1294 rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, value, &cmd);
1295 continue;
1296 }
1297 }
1298 rule_add_key(&rule_tmp, TK_M_IMPORT_PROG, op, value, NULL);
1299 } else if (streq(attr, "builtin")) {
1300 enum udev_builtin_cmd cmd = udev_builtin_lookup(value);
1301
1302 if (cmd < UDEV_BUILTIN_MAX)
1303 rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, value, &cmd);
1304 else
1305 log_error("IMPORT{builtin}: '%s' unknown %s:%u", value, filename, lineno);
1306 } else if (streq(attr, "file")) {
1307 rule_add_key(&rule_tmp, TK_M_IMPORT_FILE, op, value, NULL);
1308 } else if (streq(attr, "db")) {
1309 rule_add_key(&rule_tmp, TK_M_IMPORT_DB, op, value, NULL);
1310 } else if (streq(attr, "cmdline")) {
1311 rule_add_key(&rule_tmp, TK_M_IMPORT_CMDLINE, op, value, NULL);
1312 } else if (streq(attr, "parent")) {
1313 rule_add_key(&rule_tmp, TK_M_IMPORT_PARENT, op, value, NULL);
1314 } else
1315 log_error("IMPORT{} unknown type, ignoring IMPORT %s:%u", filename, lineno);
1316 continue;
1317 }
1318
1319 if (startswith(key, "TEST")) {
1320 mode_t mode = 0;
1321
1322 if (op > OP_MATCH_MAX) {
1323 log_error("invalid TEST operation");
1324 goto invalid;
1325 }
1326 attr = get_key_attribute(rules->udev, key + strlen("TEST"));
1327 if (attr != NULL) {
1328 mode = strtol(attr, NULL, 8);
1329 rule_add_key(&rule_tmp, TK_M_TEST, op, value, &mode);
1330 } else {
1331 rule_add_key(&rule_tmp, TK_M_TEST, op, value, NULL);
1332 }
1333 continue;
1334 }
1335
1336 if (startswith(key, "RUN")) {
1337 attr = get_key_attribute(rules->udev, key + strlen("RUN"));
1338 if (attr == NULL)
1339 attr = "program";
1340 if (op == OP_REMOVE) {
1341 log_error("invalid RUN operation");
1342 goto invalid;
1343 }
1344
1345 if (streq(attr, "builtin")) {
1346 enum udev_builtin_cmd cmd = udev_builtin_lookup(value);
1347
1348 if (cmd < UDEV_BUILTIN_MAX)
1349 rule_add_key(&rule_tmp, TK_A_RUN_BUILTIN, op, value, &cmd);
1350 else
1351 log_error("RUN{builtin}: '%s' unknown %s:%u", value, filename, lineno);
1352 } else if (streq(attr, "program")) {
1353 enum udev_builtin_cmd cmd = UDEV_BUILTIN_MAX;
1354
1355 rule_add_key(&rule_tmp, TK_A_RUN_PROGRAM, op, value, &cmd);
1356 } else {
1357 log_error("RUN{} unknown type, ignoring RUN %s:%u", filename, lineno);
1358 }
1359
1360 continue;
1361 }
1362
1363 if (streq(key, "LABEL")) {
1364 if (op == OP_REMOVE) {
1365 log_error("invalid LABEL operation");
1366 goto invalid;
1367 }
1368 rule_tmp.rule.rule.label_off = rules_add_string(rules, value);
1369 continue;
1370 }
1371
1372 if (streq(key, "GOTO")) {
1373 if (op == OP_REMOVE) {
1374 log_error("invalid GOTO operation");
1375 goto invalid;
1376 }
1377 rule_add_key(&rule_tmp, TK_A_GOTO, 0, value, NULL);
1378 continue;
1379 }
1380
1381 if (startswith(key, "NAME")) {
1382 if (op == OP_REMOVE) {
1383 log_error("invalid NAME operation");
1384 goto invalid;
1385 }
1386 if (op < OP_MATCH_MAX) {
1387 rule_add_key(&rule_tmp, TK_M_NAME, op, value, NULL);
1388 } else {
1389 if (streq(value, "%k")) {
1390 log_error("NAME=\"%%k\" is ignored, because it breaks kernel supplied names, "
1391 "please remove it from %s:%u\n", filename, lineno);
1392 continue;
1393 }
1394 if (value[0] == '\0') {
1395 log_debug("NAME=\"\" is ignored, because udev will not delete any device nodes, "
1396 "please remove it from %s:%u\n", filename, lineno);
1397 continue;
1398 }
1399 rule_add_key(&rule_tmp, TK_A_NAME, op, value, NULL);
1400 }
1401 rule_tmp.rule.rule.can_set_name = true;
1402 continue;
1403 }
1404
1405 if (streq(key, "SYMLINK")) {
1406 if (op == OP_REMOVE) {
1407 log_error("invalid SYMLINK operation");
1408 goto invalid;
1409 }
1410 if (op < OP_MATCH_MAX)
1411 rule_add_key(&rule_tmp, TK_M_DEVLINK, op, value, NULL);
1412 else
1413 rule_add_key(&rule_tmp, TK_A_DEVLINK, op, value, NULL);
1414 rule_tmp.rule.rule.can_set_name = true;
1415 continue;
1416 }
1417
1418 if (streq(key, "OWNER")) {
1419 uid_t uid;
1420 char *endptr;
1421
1422 if (op == OP_REMOVE) {
1423 log_error("invalid OWNER operation");
1424 goto invalid;
1425 }
1426
1427 uid = strtoul(value, &endptr, 10);
1428 if (endptr[0] == '\0') {
1429 rule_add_key(&rule_tmp, TK_A_OWNER_ID, op, NULL, &uid);
1430 } else if ((rules->resolve_names > 0) && strchr("$%", value[0]) == NULL) {
1431 uid = add_uid(rules, value);
1432 rule_add_key(&rule_tmp, TK_A_OWNER_ID, op, NULL, &uid);
1433 } else if (rules->resolve_names >= 0)
1434 rule_add_key(&rule_tmp, TK_A_OWNER, op, value, NULL);
1435
1436 rule_tmp.rule.rule.can_set_name = true;
1437 continue;
1438 }
1439
1440 if (streq(key, "GROUP")) {
1441 gid_t gid;
1442 char *endptr;
1443
1444 if (op == OP_REMOVE) {
1445 log_error("invalid GROUP operation");
1446 goto invalid;
1447 }
1448
1449 gid = strtoul(value, &endptr, 10);
1450 if (endptr[0] == '\0') {
1451 rule_add_key(&rule_tmp, TK_A_GROUP_ID, op, NULL, &gid);
1452 } else if ((rules->resolve_names > 0) && strchr("$%", value[0]) == NULL) {
1453 gid = add_gid(rules, value);
1454 rule_add_key(&rule_tmp, TK_A_GROUP_ID, op, NULL, &gid);
1455 } else if (rules->resolve_names >= 0)
1456 rule_add_key(&rule_tmp, TK_A_GROUP, op, value, NULL);
1457
1458 rule_tmp.rule.rule.can_set_name = true;
1459 continue;
1460 }
1461
1462 if (streq(key, "MODE")) {
1463 mode_t mode;
1464 char *endptr;
1465
1466 if (op == OP_REMOVE) {
1467 log_error("invalid MODE operation");
1468 goto invalid;
1469 }
1470
1471 mode = strtol(value, &endptr, 8);
1472 if (endptr[0] == '\0')
1473 rule_add_key(&rule_tmp, TK_A_MODE_ID, op, NULL, &mode);
1474 else
1475 rule_add_key(&rule_tmp, TK_A_MODE, op, value, NULL);
1476 rule_tmp.rule.rule.can_set_name = true;
1477 continue;
1478 }
1479
1480 if (streq(key, "OPTIONS")) {
1481 const char *pos;
1482
1483 if (op == OP_REMOVE) {
1484 log_error("invalid OPTIONS operation");
1485 goto invalid;
1486 }
1487
1488 pos = strstr(value, "link_priority=");
1489 if (pos != NULL) {
1490 int prio = atoi(&pos[strlen("link_priority=")]);
1491
1492 rule_add_key(&rule_tmp, TK_A_DEVLINK_PRIO, op, NULL, &prio);
1493 }
1494
1495 pos = strstr(value, "string_escape=");
1496 if (pos != NULL) {
1497 pos = &pos[strlen("string_escape=")];
1498 if (startswith(pos, "none"))
1499 rule_add_key(&rule_tmp, TK_A_STRING_ESCAPE_NONE, op, NULL, NULL);
1500 else if (startswith(pos, "replace"))
1501 rule_add_key(&rule_tmp, TK_A_STRING_ESCAPE_REPLACE, op, NULL, NULL);
1502 }
1503
1504 pos = strstr(value, "db_persist");
1505 if (pos != NULL)
1506 rule_add_key(&rule_tmp, TK_A_DB_PERSIST, op, NULL, NULL);
1507
1508 pos = strstr(value, "nowatch");
1509 if (pos != NULL) {
1510 const int off = 0;
1511
1512 rule_add_key(&rule_tmp, TK_A_INOTIFY_WATCH, op, NULL, &off);
1513 } else {
1514 pos = strstr(value, "watch");
1515 if (pos != NULL) {
1516 const int on = 1;
1517
1518 rule_add_key(&rule_tmp, TK_A_INOTIFY_WATCH, op, NULL, &on);
1519 }
1520 }
1521
1522 pos = strstr(value, "static_node=");
1523 if (pos != NULL) {
1524 rule_add_key(&rule_tmp, TK_A_STATIC_NODE, op, &pos[strlen("static_node=")], NULL);
1525 rule_tmp.rule.rule.has_static_node = true;
1526 }
1527
1528 continue;
1529 }
1530
1531 log_error("unknown key '%s' in %s:%u", key, filename, lineno);
1532 goto invalid;
1533 }
1534
1535 /* add rule token */
1536 rule_tmp.rule.rule.token_count = 1 + rule_tmp.token_cur;
1537 if (add_token(rules, &rule_tmp.rule) != 0)
1538 goto invalid;
1539
1540 /* add tokens to list, sorted by type */
1541 if (sort_token(rules, &rule_tmp) != 0)
1542 goto invalid;
1543
1544 return 0;
1545 invalid:
1546 log_error("invalid rule '%s:%u'", filename, lineno);
1547 return -1;
1548 }
1549
1550 static int parse_file(struct udev_rules *rules, const char *filename) {
1551 _cleanup_fclose_ FILE *f = NULL;
1552 unsigned int first_token;
1553 unsigned int filename_off;
1554 char line[UTIL_LINE_SIZE];
1555 int line_nr = 0;
1556 unsigned int i;
1557
1558 f = fopen(filename, "re");
1559 if (!f) {
1560 if (errno == ENOENT)
1561 return 0;
1562 else
1563 return -errno;
1564 }
1565
1566 if (null_or_empty_fd(fileno(f))) {
1567 log_debug("Skipping empty file: %s", filename);
1568 return 0;
1569 } else
1570 log_debug("Reading rules file: %s", filename);
1571
1572 first_token = rules->token_cur;
1573 filename_off = rules_add_string(rules, filename);
1574
1575 while (fgets(line, sizeof(line), f) != NULL) {
1576 char *key;
1577 size_t len;
1578
1579 /* skip whitespace */
1580 line_nr++;
1581 key = line;
1582 while (isspace(key[0]))
1583 key++;
1584
1585 /* comment */
1586 if (key[0] == '#')
1587 continue;
1588
1589 len = strlen(line);
1590 if (len < 3)
1591 continue;
1592
1593 /* continue reading if backslash+newline is found */
1594 while (line[len-2] == '\\') {
1595 if (fgets(&line[len-2], (sizeof(line)-len)+2, f) == NULL)
1596 break;
1597 if (strlen(&line[len-2]) < 2)
1598 break;
1599 line_nr++;
1600 len = strlen(line);
1601 }
1602
1603 if (len+1 >= sizeof(line)) {
1604 log_error("line too long '%s':%u, ignored", filename, line_nr);
1605 continue;
1606 }
1607 add_rule(rules, key, filename, filename_off, line_nr);
1608 }
1609
1610 /* link GOTOs to LABEL rules in this file to be able to fast-forward */
1611 for (i = first_token+1; i < rules->token_cur; i++) {
1612 if (rules->tokens[i].type == TK_A_GOTO) {
1613 char *label = rules_str(rules, rules->tokens[i].key.value_off);
1614 unsigned int j;
1615
1616 for (j = i+1; j < rules->token_cur; j++) {
1617 if (rules->tokens[j].type != TK_RULE)
1618 continue;
1619 if (rules->tokens[j].rule.label_off == 0)
1620 continue;
1621 if (!streq(label, rules_str(rules, rules->tokens[j].rule.label_off)))
1622 continue;
1623 rules->tokens[i].key.rule_goto = j;
1624 break;
1625 }
1626 if (rules->tokens[i].key.rule_goto == 0)
1627 log_error("GOTO '%s' has no matching label in: '%s'", label, filename);
1628 }
1629 }
1630 return 0;
1631 }
1632
1633 struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names) {
1634 struct udev_rules *rules;
1635 struct udev_list file_list;
1636 struct token end_token;
1637 char **files, **f;
1638 int r;
1639
1640 rules = new0(struct udev_rules, 1);
1641 if (rules == NULL)
1642 return NULL;
1643 rules->udev = udev;
1644 rules->resolve_names = resolve_names;
1645 udev_list_init(udev, &file_list, true);
1646
1647 /* init token array and string buffer */
1648 rules->tokens = malloc(PREALLOC_TOKEN * sizeof(struct token));
1649 if (rules->tokens == NULL)
1650 return udev_rules_unref(rules);
1651 rules->token_max = PREALLOC_TOKEN;
1652
1653 rules->strbuf = strbuf_new();
1654 if (!rules->strbuf)
1655 return udev_rules_unref(rules);
1656
1657 udev_rules_check_timestamp(rules);
1658
1659 r = conf_files_list_strv(&files, ".rules", NULL, rules_dirs);
1660 if (r < 0) {
1661 log_error_errno(r, "failed to enumerate rules files: %m");
1662 return udev_rules_unref(rules);
1663 }
1664
1665 /*
1666 * The offset value in the rules strct is limited; add all
1667 * rules file names to the beginning of the string buffer.
1668 */
1669 STRV_FOREACH(f, files)
1670 rules_add_string(rules, *f);
1671
1672 STRV_FOREACH(f, files)
1673 parse_file(rules, *f);
1674
1675 strv_free(files);
1676
1677 memzero(&end_token, sizeof(struct token));
1678 end_token.type = TK_END;
1679 add_token(rules, &end_token);
1680 log_debug("rules contain %zu bytes tokens (%u * %zu bytes), %zu bytes strings",
1681 rules->token_max * sizeof(struct token), rules->token_max, sizeof(struct token), rules->strbuf->len);
1682
1683 /* cleanup temporary strbuf data */
1684 log_debug("%zu strings (%zu bytes), %zu de-duplicated (%zu bytes), %zu trie nodes used",
1685 rules->strbuf->in_count, rules->strbuf->in_len,
1686 rules->strbuf->dedup_count, rules->strbuf->dedup_len, rules->strbuf->nodes_count);
1687 strbuf_complete(rules->strbuf);
1688
1689 /* cleanup uid/gid cache */
1690 rules->uids = mfree(rules->uids);
1691 rules->uids_cur = 0;
1692 rules->uids_max = 0;
1693 rules->gids = mfree(rules->gids);
1694 rules->gids_cur = 0;
1695 rules->gids_max = 0;
1696
1697 dump_rules(rules);
1698 return rules;
1699 }
1700
1701 struct udev_rules *udev_rules_unref(struct udev_rules *rules) {
1702 if (rules == NULL)
1703 return NULL;
1704 free(rules->tokens);
1705 strbuf_cleanup(rules->strbuf);
1706 free(rules->uids);
1707 free(rules->gids);
1708 free(rules);
1709 return NULL;
1710 }
1711
1712 bool udev_rules_check_timestamp(struct udev_rules *rules) {
1713 if (!rules)
1714 return false;
1715
1716 return paths_check_timestamp(rules_dirs, &rules->dirs_ts_usec, true);
1717 }
1718
1719 static int match_key(struct udev_rules *rules, struct token *token, const char *val) {
1720 char *key_value = rules_str(rules, token->key.value_off);
1721 char *pos;
1722 bool match = false;
1723
1724 if (val == NULL)
1725 val = "";
1726
1727 switch (token->key.glob) {
1728 case GL_PLAIN:
1729 match = (streq(key_value, val));
1730 break;
1731 case GL_GLOB:
1732 match = (fnmatch(key_value, val, 0) == 0);
1733 break;
1734 case GL_SPLIT:
1735 {
1736 const char *s;
1737 size_t len;
1738
1739 s = rules_str(rules, token->key.value_off);
1740 len = strlen(val);
1741 for (;;) {
1742 const char *next;
1743
1744 next = strchr(s, '|');
1745 if (next != NULL) {
1746 size_t matchlen = (size_t)(next - s);
1747
1748 match = (matchlen == len && strneq(s, val, matchlen));
1749 if (match)
1750 break;
1751 } else {
1752 match = (streq(s, val));
1753 break;
1754 }
1755 s = &next[1];
1756 }
1757 break;
1758 }
1759 case GL_SPLIT_GLOB:
1760 {
1761 char value[UTIL_PATH_SIZE];
1762
1763 strscpy(value, sizeof(value), rules_str(rules, token->key.value_off));
1764 key_value = value;
1765 while (key_value != NULL) {
1766 pos = strchr(key_value, '|');
1767 if (pos != NULL) {
1768 pos[0] = '\0';
1769 pos = &pos[1];
1770 }
1771 match = (fnmatch(key_value, val, 0) == 0);
1772 if (match)
1773 break;
1774 key_value = pos;
1775 }
1776 break;
1777 }
1778 case GL_SOMETHING:
1779 match = (val[0] != '\0');
1780 break;
1781 case GL_UNSET:
1782 return -1;
1783 }
1784
1785 if (match && (token->key.op == OP_MATCH))
1786 return 0;
1787 if (!match && (token->key.op == OP_NOMATCH))
1788 return 0;
1789 return -1;
1790 }
1791
1792 static int match_attr(struct udev_rules *rules, struct udev_device *dev, struct udev_event *event, struct token *cur) {
1793 const char *name;
1794 char nbuf[UTIL_NAME_SIZE];
1795 const char *value;
1796 char vbuf[UTIL_NAME_SIZE];
1797 size_t len;
1798
1799 name = rules_str(rules, cur->key.attr_off);
1800 switch (cur->key.attrsubst) {
1801 case SB_FORMAT:
1802 udev_event_apply_format(event, name, nbuf, sizeof(nbuf));
1803 name = nbuf;
1804 /* fall through */
1805 case SB_NONE:
1806 value = udev_device_get_sysattr_value(dev, name);
1807 if (value == NULL)
1808 return -1;
1809 break;
1810 case SB_SUBSYS:
1811 if (util_resolve_subsys_kernel(event->udev, name, vbuf, sizeof(vbuf), 1) != 0)
1812 return -1;
1813 value = vbuf;
1814 break;
1815 default:
1816 return -1;
1817 }
1818
1819 /* remove trailing whitespace, if not asked to match for it */
1820 len = strlen(value);
1821 if (len > 0 && isspace(value[len-1])) {
1822 const char *key_value;
1823 size_t klen;
1824
1825 key_value = rules_str(rules, cur->key.value_off);
1826 klen = strlen(key_value);
1827 if (klen > 0 && !isspace(key_value[klen-1])) {
1828 if (value != vbuf) {
1829 strscpy(vbuf, sizeof(vbuf), value);
1830 value = vbuf;
1831 }
1832 while (len > 0 && isspace(vbuf[--len]))
1833 vbuf[len] = '\0';
1834 }
1835 }
1836
1837 return match_key(rules, cur, value);
1838 }
1839
1840 enum escape_type {
1841 ESCAPE_UNSET,
1842 ESCAPE_NONE,
1843 ESCAPE_REPLACE,
1844 };
1845
1846 int udev_rules_apply_to_event(struct udev_rules *rules,
1847 struct udev_event *event,
1848 usec_t timeout_usec,
1849 usec_t timeout_warn_usec,
1850 struct udev_list *properties_list) {
1851 struct token *cur;
1852 struct token *rule;
1853 enum escape_type esc = ESCAPE_UNSET;
1854 bool can_set_name;
1855
1856 if (rules->tokens == NULL)
1857 return -1;
1858
1859 can_set_name = ((!streq(udev_device_get_action(event->dev), "remove")) &&
1860 (major(udev_device_get_devnum(event->dev)) > 0 ||
1861 udev_device_get_ifindex(event->dev) > 0));
1862
1863 /* loop through token list, match, run actions or forward to next rule */
1864 cur = &rules->tokens[0];
1865 rule = cur;
1866 for (;;) {
1867 dump_token(rules, cur);
1868 switch (cur->type) {
1869 case TK_RULE:
1870 /* current rule */
1871 rule = cur;
1872 /* possibly skip rules which want to set NAME, SYMLINK, OWNER, GROUP, MODE */
1873 if (!can_set_name && rule->rule.can_set_name)
1874 goto nomatch;
1875 esc = ESCAPE_UNSET;
1876 break;
1877 case TK_M_ACTION:
1878 if (match_key(rules, cur, udev_device_get_action(event->dev)) != 0)
1879 goto nomatch;
1880 break;
1881 case TK_M_DEVPATH:
1882 if (match_key(rules, cur, udev_device_get_devpath(event->dev)) != 0)
1883 goto nomatch;
1884 break;
1885 case TK_M_KERNEL:
1886 if (match_key(rules, cur, udev_device_get_sysname(event->dev)) != 0)
1887 goto nomatch;
1888 break;
1889 case TK_M_DEVLINK: {
1890 struct udev_list_entry *list_entry;
1891 bool match = false;
1892
1893 udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(event->dev)) {
1894 const char *devlink;
1895
1896 devlink = udev_list_entry_get_name(list_entry) + strlen("/dev/");
1897 if (match_key(rules, cur, devlink) == 0) {
1898 match = true;
1899 break;
1900 }
1901 }
1902 if (!match)
1903 goto nomatch;
1904 break;
1905 }
1906 case TK_M_NAME:
1907 if (match_key(rules, cur, event->name) != 0)
1908 goto nomatch;
1909 break;
1910 case TK_M_ENV: {
1911 const char *key_name = rules_str(rules, cur->key.attr_off);
1912 const char *value;
1913
1914 value = udev_device_get_property_value(event->dev, key_name);
1915
1916 /* check global properties */
1917 if (!value && properties_list) {
1918 struct udev_list_entry *list_entry;
1919
1920 list_entry = udev_list_get_entry(properties_list);
1921 list_entry = udev_list_entry_get_by_name(list_entry, key_name);
1922 if (list_entry != NULL)
1923 value = udev_list_entry_get_value(list_entry);
1924 }
1925
1926 if (!value)
1927 value = "";
1928 if (match_key(rules, cur, value))
1929 goto nomatch;
1930 break;
1931 }
1932 case TK_M_TAG: {
1933 struct udev_list_entry *list_entry;
1934 bool match = false;
1935
1936 udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(event->dev)) {
1937 if (streq(rules_str(rules, cur->key.value_off), udev_list_entry_get_name(list_entry))) {
1938 match = true;
1939 break;
1940 }
1941 }
1942 if ((!match && (cur->key.op != OP_NOMATCH)) ||
1943 (match && (cur->key.op == OP_NOMATCH)))
1944 goto nomatch;
1945 break;
1946 }
1947 case TK_M_SUBSYSTEM:
1948 if (match_key(rules, cur, udev_device_get_subsystem(event->dev)) != 0)
1949 goto nomatch;
1950 break;
1951 case TK_M_DRIVER:
1952 if (match_key(rules, cur, udev_device_get_driver(event->dev)) != 0)
1953 goto nomatch;
1954 break;
1955 case TK_M_ATTR:
1956 if (match_attr(rules, event->dev, event, cur) != 0)
1957 goto nomatch;
1958 break;
1959 case TK_M_SYSCTL: {
1960 char filename[UTIL_PATH_SIZE];
1961 _cleanup_free_ char *value = NULL;
1962 size_t len;
1963
1964 udev_event_apply_format(event, rules_str(rules, cur->key.attr_off), filename, sizeof(filename));
1965 sysctl_normalize(filename);
1966 if (sysctl_read(filename, &value) < 0)
1967 goto nomatch;
1968
1969 len = strlen(value);
1970 while (len > 0 && isspace(value[--len]))
1971 value[len] = '\0';
1972 if (match_key(rules, cur, value) != 0)
1973 goto nomatch;
1974 break;
1975 }
1976 case TK_M_KERNELS:
1977 case TK_M_SUBSYSTEMS:
1978 case TK_M_DRIVERS:
1979 case TK_M_ATTRS:
1980 case TK_M_TAGS: {
1981 struct token *next;
1982
1983 /* get whole sequence of parent matches */
1984 next = cur;
1985 while (next->type > TK_M_PARENTS_MIN && next->type < TK_M_PARENTS_MAX)
1986 next++;
1987
1988 /* loop over parents */
1989 event->dev_parent = event->dev;
1990 for (;;) {
1991 struct token *key;
1992
1993 /* loop over sequence of parent match keys */
1994 for (key = cur; key < next; key++ ) {
1995 dump_token(rules, key);
1996 switch(key->type) {
1997 case TK_M_KERNELS:
1998 if (match_key(rules, key, udev_device_get_sysname(event->dev_parent)) != 0)
1999 goto try_parent;
2000 break;
2001 case TK_M_SUBSYSTEMS:
2002 if (match_key(rules, key, udev_device_get_subsystem(event->dev_parent)) != 0)
2003 goto try_parent;
2004 break;
2005 case TK_M_DRIVERS:
2006 if (match_key(rules, key, udev_device_get_driver(event->dev_parent)) != 0)
2007 goto try_parent;
2008 break;
2009 case TK_M_ATTRS:
2010 if (match_attr(rules, event->dev_parent, event, key) != 0)
2011 goto try_parent;
2012 break;
2013 case TK_M_TAGS: {
2014 bool match = udev_device_has_tag(event->dev_parent, rules_str(rules, cur->key.value_off));
2015
2016 if (match && key->key.op == OP_NOMATCH)
2017 goto try_parent;
2018 if (!match && key->key.op == OP_MATCH)
2019 goto try_parent;
2020 break;
2021 }
2022 default:
2023 goto nomatch;
2024 }
2025 }
2026 break;
2027
2028 try_parent:
2029 event->dev_parent = udev_device_get_parent(event->dev_parent);
2030 if (event->dev_parent == NULL)
2031 goto nomatch;
2032 }
2033 /* move behind our sequence of parent match keys */
2034 cur = next;
2035 continue;
2036 }
2037 case TK_M_TEST: {
2038 char filename[UTIL_PATH_SIZE];
2039 struct stat statbuf;
2040 int match;
2041
2042 udev_event_apply_format(event, rules_str(rules, cur->key.value_off), filename, sizeof(filename));
2043 if (util_resolve_subsys_kernel(event->udev, filename, filename, sizeof(filename), 0) != 0) {
2044 if (filename[0] != '/') {
2045 char tmp[UTIL_PATH_SIZE];
2046
2047 strscpy(tmp, sizeof(tmp), filename);
2048 strscpyl(filename, sizeof(filename),
2049 udev_device_get_syspath(event->dev), "/", tmp, NULL);
2050 }
2051 }
2052 attr_subst_subdir(filename, sizeof(filename));
2053
2054 match = (stat(filename, &statbuf) == 0);
2055 if (match && cur->key.mode > 0)
2056 match = ((statbuf.st_mode & cur->key.mode) > 0);
2057 if (match && cur->key.op == OP_NOMATCH)
2058 goto nomatch;
2059 if (!match && cur->key.op == OP_MATCH)
2060 goto nomatch;
2061 break;
2062 }
2063 case TK_M_PROGRAM: {
2064 char program[UTIL_PATH_SIZE];
2065 char result[UTIL_LINE_SIZE];
2066
2067 event->program_result = mfree(event->program_result);
2068 udev_event_apply_format(event, rules_str(rules, cur->key.value_off), program, sizeof(program));
2069 log_debug("PROGRAM '%s' %s:%u",
2070 program,
2071 rules_str(rules, rule->rule.filename_off),
2072 rule->rule.filename_line);
2073
2074 if (udev_event_spawn(event, timeout_usec, timeout_warn_usec, true, program, result, sizeof(result)) < 0) {
2075 if (cur->key.op != OP_NOMATCH)
2076 goto nomatch;
2077 } else {
2078 int count;
2079
2080 util_remove_trailing_chars(result, '\n');
2081 if (esc == ESCAPE_UNSET || esc == ESCAPE_REPLACE) {
2082 count = util_replace_chars(result, UDEV_ALLOWED_CHARS_INPUT);
2083 if (count > 0)
2084 log_debug("%i character(s) replaced" , count);
2085 }
2086 event->program_result = strdup(result);
2087 if (cur->key.op == OP_NOMATCH)
2088 goto nomatch;
2089 }
2090 break;
2091 }
2092 case TK_M_IMPORT_FILE: {
2093 char import[UTIL_PATH_SIZE];
2094
2095 udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import));
2096 if (import_file_into_properties(event->dev, import) != 0)
2097 if (cur->key.op != OP_NOMATCH)
2098 goto nomatch;
2099 break;
2100 }
2101 case TK_M_IMPORT_PROG: {
2102 char import[UTIL_PATH_SIZE];
2103
2104 udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import));
2105 log_debug("IMPORT '%s' %s:%u",
2106 import,
2107 rules_str(rules, rule->rule.filename_off),
2108 rule->rule.filename_line);
2109
2110 if (import_program_into_properties(event, timeout_usec, timeout_warn_usec, import) != 0)
2111 if (cur->key.op != OP_NOMATCH)
2112 goto nomatch;
2113 break;
2114 }
2115 case TK_M_IMPORT_BUILTIN: {
2116 char command[UTIL_PATH_SIZE];
2117
2118 if (udev_builtin_run_once(cur->key.builtin_cmd)) {
2119 /* check if we ran already */
2120 if (event->builtin_run & (1 << cur->key.builtin_cmd)) {
2121 log_debug("IMPORT builtin skip '%s' %s:%u",
2122 udev_builtin_name(cur->key.builtin_cmd),
2123 rules_str(rules, rule->rule.filename_off),
2124 rule->rule.filename_line);
2125 /* return the result from earlier run */
2126 if (event->builtin_ret & (1 << cur->key.builtin_cmd))
2127 if (cur->key.op != OP_NOMATCH)
2128 goto nomatch;
2129 break;
2130 }
2131 /* mark as ran */
2132 event->builtin_run |= (1 << cur->key.builtin_cmd);
2133 }
2134
2135 udev_event_apply_format(event, rules_str(rules, cur->key.value_off), command, sizeof(command));
2136 log_debug("IMPORT builtin '%s' %s:%u",
2137 udev_builtin_name(cur->key.builtin_cmd),
2138 rules_str(rules, rule->rule.filename_off),
2139 rule->rule.filename_line);
2140
2141 if (udev_builtin_run(event->dev, cur->key.builtin_cmd, command, false) != 0) {
2142 /* remember failure */
2143 log_debug("IMPORT builtin '%s' returned non-zero",
2144 udev_builtin_name(cur->key.builtin_cmd));
2145 event->builtin_ret |= (1 << cur->key.builtin_cmd);
2146 if (cur->key.op != OP_NOMATCH)
2147 goto nomatch;
2148 }
2149 break;
2150 }
2151 case TK_M_IMPORT_DB: {
2152 const char *key = rules_str(rules, cur->key.value_off);
2153 const char *value;
2154
2155 value = udev_device_get_property_value(event->dev_db, key);
2156 if (value != NULL)
2157 udev_device_add_property(event->dev, key, value);
2158 else {
2159 if (cur->key.op != OP_NOMATCH)
2160 goto nomatch;
2161 }
2162 break;
2163 }
2164 case TK_M_IMPORT_CMDLINE: {
2165 FILE *f;
2166 bool imported = false;
2167
2168 f = fopen("/proc/cmdline", "re");
2169 if (f != NULL) {
2170 char cmdline[4096];
2171
2172 if (fgets(cmdline, sizeof(cmdline), f) != NULL) {
2173 const char *key = rules_str(rules, cur->key.value_off);
2174 char *pos;
2175
2176 pos = strstr(cmdline, key);
2177 if (pos != NULL) {
2178 pos += strlen(key);
2179 if (pos[0] == '\0' || isspace(pos[0])) {
2180 /* we import simple flags as 'FLAG=1' */
2181 udev_device_add_property(event->dev, key, "1");
2182 imported = true;
2183 } else if (pos[0] == '=') {
2184 const char *value;
2185
2186 pos++;
2187 value = pos;
2188 while (pos[0] != '\0' && !isspace(pos[0]))
2189 pos++;
2190 pos[0] = '\0';
2191 udev_device_add_property(event->dev, key, value);
2192 imported = true;
2193 }
2194 }
2195 }
2196 fclose(f);
2197 }
2198 if (!imported && cur->key.op != OP_NOMATCH)
2199 goto nomatch;
2200 break;
2201 }
2202 case TK_M_IMPORT_PARENT: {
2203 char import[UTIL_PATH_SIZE];
2204
2205 udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import));
2206 if (import_parent_into_properties(event->dev, import) != 0)
2207 if (cur->key.op != OP_NOMATCH)
2208 goto nomatch;
2209 break;
2210 }
2211 case TK_M_RESULT:
2212 if (match_key(rules, cur, event->program_result) != 0)
2213 goto nomatch;
2214 break;
2215 case TK_A_STRING_ESCAPE_NONE:
2216 esc = ESCAPE_NONE;
2217 break;
2218 case TK_A_STRING_ESCAPE_REPLACE:
2219 esc = ESCAPE_REPLACE;
2220 break;
2221 case TK_A_DB_PERSIST:
2222 udev_device_set_db_persist(event->dev);
2223 break;
2224 case TK_A_INOTIFY_WATCH:
2225 if (event->inotify_watch_final)
2226 break;
2227 if (cur->key.op == OP_ASSIGN_FINAL)
2228 event->inotify_watch_final = true;
2229 event->inotify_watch = cur->key.watch;
2230 break;
2231 case TK_A_DEVLINK_PRIO:
2232 udev_device_set_devlink_priority(event->dev, cur->key.devlink_prio);
2233 break;
2234 case TK_A_OWNER: {
2235 char owner[UTIL_NAME_SIZE];
2236 const char *ow = owner;
2237 int r;
2238
2239 if (event->owner_final)
2240 break;
2241 if (cur->key.op == OP_ASSIGN_FINAL)
2242 event->owner_final = true;
2243 udev_event_apply_format(event, rules_str(rules, cur->key.value_off), owner, sizeof(owner));
2244 event->owner_set = true;
2245 r = get_user_creds(&ow, &event->uid, NULL, NULL, NULL);
2246 if (r < 0) {
2247 if (r == -ENOENT || r == -ESRCH)
2248 log_error("specified user '%s' unknown", owner);
2249 else
2250 log_error_errno(r, "error resolving user '%s': %m", owner);
2251
2252 event->uid = 0;
2253 }
2254 log_debug("OWNER %u %s:%u",
2255 event->uid,
2256 rules_str(rules, rule->rule.filename_off),
2257 rule->rule.filename_line);
2258 break;
2259 }
2260 case TK_A_GROUP: {
2261 char group[UTIL_NAME_SIZE];
2262 const char *gr = group;
2263 int r;
2264
2265 if (event->group_final)
2266 break;
2267 if (cur->key.op == OP_ASSIGN_FINAL)
2268 event->group_final = true;
2269 udev_event_apply_format(event, rules_str(rules, cur->key.value_off), group, sizeof(group));
2270 event->group_set = true;
2271 r = get_group_creds(&gr, &event->gid);
2272 if (r < 0) {
2273 if (r == -ENOENT || r == -ESRCH)
2274 log_error("specified group '%s' unknown", group);
2275 else
2276 log_error_errno(r, "error resolving group '%s': %m", group);
2277
2278 event->gid = 0;
2279 }
2280 log_debug("GROUP %u %s:%u",
2281 event->gid,
2282 rules_str(rules, rule->rule.filename_off),
2283 rule->rule.filename_line);
2284 break;
2285 }
2286 case TK_A_MODE: {
2287 char mode_str[UTIL_NAME_SIZE];
2288 mode_t mode;
2289 char *endptr;
2290
2291 if (event->mode_final)
2292 break;
2293 udev_event_apply_format(event, rules_str(rules, cur->key.value_off), mode_str, sizeof(mode_str));
2294 mode = strtol(mode_str, &endptr, 8);
2295 if (endptr[0] != '\0') {
2296 log_error("ignoring invalid mode '%s'", mode_str);
2297 break;
2298 }
2299 if (cur->key.op == OP_ASSIGN_FINAL)
2300 event->mode_final = true;
2301 event->mode_set = true;
2302 event->mode = mode;
2303 log_debug("MODE %#o %s:%u",
2304 event->mode,
2305 rules_str(rules, rule->rule.filename_off),
2306 rule->rule.filename_line);
2307 break;
2308 }
2309 case TK_A_OWNER_ID:
2310 if (event->owner_final)
2311 break;
2312 if (cur->key.op == OP_ASSIGN_FINAL)
2313 event->owner_final = true;
2314 event->owner_set = true;
2315 event->uid = cur->key.uid;
2316 log_debug("OWNER %u %s:%u",
2317 event->uid,
2318 rules_str(rules, rule->rule.filename_off),
2319 rule->rule.filename_line);
2320 break;
2321 case TK_A_GROUP_ID:
2322 if (event->group_final)
2323 break;
2324 if (cur->key.op == OP_ASSIGN_FINAL)
2325 event->group_final = true;
2326 event->group_set = true;
2327 event->gid = cur->key.gid;
2328 log_debug("GROUP %u %s:%u",
2329 event->gid,
2330 rules_str(rules, rule->rule.filename_off),
2331 rule->rule.filename_line);
2332 break;
2333 case TK_A_MODE_ID:
2334 if (event->mode_final)
2335 break;
2336 if (cur->key.op == OP_ASSIGN_FINAL)
2337 event->mode_final = true;
2338 event->mode_set = true;
2339 event->mode = cur->key.mode;
2340 log_debug("MODE %#o %s:%u",
2341 event->mode,
2342 rules_str(rules, rule->rule.filename_off),
2343 rule->rule.filename_line);
2344 break;
2345 case TK_A_SECLABEL: {
2346 const char *name, *label;
2347
2348 name = rules_str(rules, cur->key.attr_off);
2349 label = rules_str(rules, cur->key.value_off);
2350 if (cur->key.op == OP_ASSIGN || cur->key.op == OP_ASSIGN_FINAL)
2351 udev_list_cleanup(&event->seclabel_list);
2352 udev_list_entry_add(&event->seclabel_list, name, label);
2353 log_debug("SECLABEL{%s}='%s' %s:%u",
2354 name, label,
2355 rules_str(rules, rule->rule.filename_off),
2356 rule->rule.filename_line);
2357 break;
2358 }
2359 case TK_A_ENV: {
2360 const char *name = rules_str(rules, cur->key.attr_off);
2361 char *value = rules_str(rules, cur->key.value_off);
2362 char value_new[UTIL_NAME_SIZE];
2363 const char *value_old = NULL;
2364
2365 if (value[0] == '\0') {
2366 if (cur->key.op == OP_ADD)
2367 break;
2368 udev_device_add_property(event->dev, name, NULL);
2369 break;
2370 }
2371
2372 if (cur->key.op == OP_ADD)
2373 value_old = udev_device_get_property_value(event->dev, name);
2374 if (value_old) {
2375 char temp[UTIL_NAME_SIZE];
2376
2377 /* append value separated by space */
2378 udev_event_apply_format(event, value, temp, sizeof(temp));
2379 strscpyl(value_new, sizeof(value_new), value_old, " ", temp, NULL);
2380 } else
2381 udev_event_apply_format(event, value, value_new, sizeof(value_new));
2382
2383 udev_device_add_property(event->dev, name, value_new);
2384 break;
2385 }
2386 case TK_A_TAG: {
2387 char tag[UTIL_PATH_SIZE];
2388 const char *p;
2389
2390 udev_event_apply_format(event, rules_str(rules, cur->key.value_off), tag, sizeof(tag));
2391 if (cur->key.op == OP_ASSIGN || cur->key.op == OP_ASSIGN_FINAL)
2392 udev_device_cleanup_tags_list(event->dev);
2393 for (p = tag; *p != '\0'; p++) {
2394 if ((*p >= 'a' && *p <= 'z') ||
2395 (*p >= 'A' && *p <= 'Z') ||
2396 (*p >= '0' && *p <= '9') ||
2397 *p == '-' || *p == '_')
2398 continue;
2399 log_error("ignoring invalid tag name '%s'", tag);
2400 break;
2401 }
2402 if (cur->key.op == OP_REMOVE)
2403 udev_device_remove_tag(event->dev, tag);
2404 else
2405 udev_device_add_tag(event->dev, tag);
2406 break;
2407 }
2408 case TK_A_NAME: {
2409 const char *name = rules_str(rules, cur->key.value_off);
2410
2411 char name_str[UTIL_PATH_SIZE];
2412 int count;
2413
2414 if (event->name_final)
2415 break;
2416 if (cur->key.op == OP_ASSIGN_FINAL)
2417 event->name_final = true;
2418 udev_event_apply_format(event, name, name_str, sizeof(name_str));
2419 if (esc == ESCAPE_UNSET || esc == ESCAPE_REPLACE) {
2420 count = util_replace_chars(name_str, "/");
2421 if (count > 0)
2422 log_debug("%i character(s) replaced", count);
2423 }
2424 if (major(udev_device_get_devnum(event->dev)) &&
2425 (!streq(name_str, udev_device_get_devnode(event->dev) + strlen("/dev/")))) {
2426 log_error("NAME=\"%s\" ignored, kernel device nodes "
2427 "can not be renamed; please fix it in %s:%u\n", name,
2428 rules_str(rules, rule->rule.filename_off), rule->rule.filename_line);
2429 break;
2430 }
2431 free_and_strdup(&event->name, name_str);
2432 log_debug("NAME '%s' %s:%u",
2433 event->name,
2434 rules_str(rules, rule->rule.filename_off),
2435 rule->rule.filename_line);
2436 break;
2437 }
2438 case TK_A_DEVLINK: {
2439 char temp[UTIL_PATH_SIZE];
2440 char filename[UTIL_PATH_SIZE];
2441 char *pos, *next;
2442 int count = 0;
2443
2444 if (event->devlink_final)
2445 break;
2446 if (major(udev_device_get_devnum(event->dev)) == 0)
2447 break;
2448 if (cur->key.op == OP_ASSIGN_FINAL)
2449 event->devlink_final = true;
2450 if (cur->key.op == OP_ASSIGN || cur->key.op == OP_ASSIGN_FINAL)
2451 udev_device_cleanup_devlinks_list(event->dev);
2452
2453 /* allow multiple symlinks separated by spaces */
2454 udev_event_apply_format(event, rules_str(rules, cur->key.value_off), temp, sizeof(temp));
2455 if (esc == ESCAPE_UNSET)
2456 count = util_replace_chars(temp, "/ ");
2457 else if (esc == ESCAPE_REPLACE)
2458 count = util_replace_chars(temp, "/");
2459 if (count > 0)
2460 log_debug("%i character(s) replaced" , count);
2461 pos = temp;
2462 while (isspace(pos[0]))
2463 pos++;
2464 next = strchr(pos, ' ');
2465 while (next != NULL) {
2466 next[0] = '\0';
2467 log_debug("LINK '%s' %s:%u", pos,
2468 rules_str(rules, rule->rule.filename_off), rule->rule.filename_line);
2469 strscpyl(filename, sizeof(filename), "/dev/", pos, NULL);
2470 udev_device_add_devlink(event->dev, filename);
2471 while (isspace(next[1]))
2472 next++;
2473 pos = &next[1];
2474 next = strchr(pos, ' ');
2475 }
2476 if (pos[0] != '\0') {
2477 log_debug("LINK '%s' %s:%u", pos,
2478 rules_str(rules, rule->rule.filename_off), rule->rule.filename_line);
2479 strscpyl(filename, sizeof(filename), "/dev/", pos, NULL);
2480 udev_device_add_devlink(event->dev, filename);
2481 }
2482 break;
2483 }
2484 case TK_A_ATTR: {
2485 const char *key_name = rules_str(rules, cur->key.attr_off);
2486 char attr[UTIL_PATH_SIZE];
2487 char value[UTIL_NAME_SIZE];
2488 FILE *f;
2489
2490 if (util_resolve_subsys_kernel(event->udev, key_name, attr, sizeof(attr), 0) != 0)
2491 strscpyl(attr, sizeof(attr), udev_device_get_syspath(event->dev), "/", key_name, NULL);
2492 attr_subst_subdir(attr, sizeof(attr));
2493
2494 udev_event_apply_format(event, rules_str(rules, cur->key.value_off), value, sizeof(value));
2495 log_debug("ATTR '%s' writing '%s' %s:%u", attr, value,
2496 rules_str(rules, rule->rule.filename_off),
2497 rule->rule.filename_line);
2498 f = fopen(attr, "we");
2499 if (f != NULL) {
2500 if (fprintf(f, "%s", value) <= 0)
2501 log_error_errno(errno, "error writing ATTR{%s}: %m", attr);
2502 fclose(f);
2503 } else {
2504 log_error_errno(errno, "error opening ATTR{%s} for writing: %m", attr);
2505 }
2506 break;
2507 }
2508 case TK_A_SYSCTL: {
2509 char filename[UTIL_PATH_SIZE];
2510 char value[UTIL_NAME_SIZE];
2511 int r;
2512
2513 udev_event_apply_format(event, rules_str(rules, cur->key.attr_off), filename, sizeof(filename));
2514 sysctl_normalize(filename);
2515 udev_event_apply_format(event, rules_str(rules, cur->key.value_off), value, sizeof(value));
2516 log_debug("SYSCTL '%s' writing '%s' %s:%u", filename, value,
2517 rules_str(rules, rule->rule.filename_off), rule->rule.filename_line);
2518 r = sysctl_write(filename, value);
2519 if (r < 0)
2520 log_error_errno(r, "error writing SYSCTL{%s}='%s': %m", filename, value);
2521 break;
2522 }
2523 case TK_A_RUN_BUILTIN:
2524 case TK_A_RUN_PROGRAM: {
2525 struct udev_list_entry *entry;
2526
2527 if (cur->key.op == OP_ASSIGN || cur->key.op == OP_ASSIGN_FINAL)
2528 udev_list_cleanup(&event->run_list);
2529 log_debug("RUN '%s' %s:%u",
2530 rules_str(rules, cur->key.value_off),
2531 rules_str(rules, rule->rule.filename_off),
2532 rule->rule.filename_line);
2533 entry = udev_list_entry_add(&event->run_list, rules_str(rules, cur->key.value_off), NULL);
2534 udev_list_entry_set_num(entry, cur->key.builtin_cmd);
2535 break;
2536 }
2537 case TK_A_GOTO:
2538 if (cur->key.rule_goto == 0)
2539 break;
2540 cur = &rules->tokens[cur->key.rule_goto];
2541 continue;
2542 case TK_END:
2543 return 0;
2544
2545 case TK_M_PARENTS_MIN:
2546 case TK_M_PARENTS_MAX:
2547 case TK_M_MAX:
2548 case TK_UNSET:
2549 log_error("wrong type %u", cur->type);
2550 goto nomatch;
2551 }
2552
2553 cur++;
2554 continue;
2555 nomatch:
2556 /* fast-forward to next rule */
2557 cur = rule + rule->rule.token_count;
2558 }
2559 }
2560
2561 int udev_rules_apply_static_dev_perms(struct udev_rules *rules) {
2562 struct token *cur;
2563 struct token *rule;
2564 uid_t uid = 0;
2565 gid_t gid = 0;
2566 mode_t mode = 0;
2567 _cleanup_strv_free_ char **tags = NULL;
2568 char **t;
2569 FILE *f = NULL;
2570 _cleanup_free_ char *path = NULL;
2571 int r = 0;
2572
2573 if (rules->tokens == NULL)
2574 return 0;
2575
2576 cur = &rules->tokens[0];
2577 rule = cur;
2578 for (;;) {
2579 switch (cur->type) {
2580 case TK_RULE:
2581 /* current rule */
2582 rule = cur;
2583
2584 /* skip rules without a static_node tag */
2585 if (!rule->rule.has_static_node)
2586 goto next;
2587
2588 uid = 0;
2589 gid = 0;
2590 mode = 0;
2591 tags = strv_free(tags);
2592 break;
2593 case TK_A_OWNER_ID:
2594 uid = cur->key.uid;
2595 break;
2596 case TK_A_GROUP_ID:
2597 gid = cur->key.gid;
2598 break;
2599 case TK_A_MODE_ID:
2600 mode = cur->key.mode;
2601 break;
2602 case TK_A_TAG:
2603 r = strv_extend(&tags, rules_str(rules, cur->key.value_off));
2604 if (r < 0)
2605 goto finish;
2606
2607 break;
2608 case TK_A_STATIC_NODE: {
2609 char device_node[UTIL_PATH_SIZE];
2610 char tags_dir[UTIL_PATH_SIZE];
2611 char tag_symlink[UTIL_PATH_SIZE];
2612 struct stat stats;
2613
2614 /* we assure, that the permissions tokens are sorted before the static token */
2615
2616 if (mode == 0 && uid == 0 && gid == 0 && tags == NULL)
2617 goto next;
2618
2619 strscpyl(device_node, sizeof(device_node), "/dev/", rules_str(rules, cur->key.value_off), NULL);
2620 if (stat(device_node, &stats) != 0)
2621 break;
2622 if (!S_ISBLK(stats.st_mode) && !S_ISCHR(stats.st_mode))
2623 break;
2624
2625 /* export the tags to a directory as symlinks, allowing otherwise dead nodes to be tagged */
2626 if (tags) {
2627 STRV_FOREACH(t, tags) {
2628 _cleanup_free_ char *unescaped_filename = NULL;
2629
2630 strscpyl(tags_dir, sizeof(tags_dir), "/run/udev/static_node-tags/", *t, "/", NULL);
2631 r = mkdir_p(tags_dir, 0755);
2632 if (r < 0)
2633 return log_error_errno(r, "failed to create %s: %m", tags_dir);
2634
2635 unescaped_filename = xescape(rules_str(rules, cur->key.value_off), "/.");
2636
2637 strscpyl(tag_symlink, sizeof(tag_symlink), tags_dir, unescaped_filename, NULL);
2638 r = symlink(device_node, tag_symlink);
2639 if (r < 0 && errno != EEXIST)
2640 return log_error_errno(errno, "failed to create symlink %s -> %s: %m",
2641 tag_symlink, device_node);
2642 else
2643 r = 0;
2644 }
2645 }
2646
2647 /* don't touch the permissions if only the tags were set */
2648 if (mode == 0 && uid == 0 && gid == 0)
2649 break;
2650
2651 if (mode == 0) {
2652 if (gid > 0)
2653 mode = 0660;
2654 else
2655 mode = 0600;
2656 }
2657 if (mode != (stats.st_mode & 01777)) {
2658 r = chmod(device_node, mode);
2659 if (r < 0) {
2660 log_error("failed to chmod '%s' %#o", device_node, mode);
2661 return -errno;
2662 } else
2663 log_debug("chmod '%s' %#o", device_node, mode);
2664 }
2665
2666 if ((uid != 0 && uid != stats.st_uid) || (gid != 0 && gid != stats.st_gid)) {
2667 r = chown(device_node, uid, gid);
2668 if (r < 0) {
2669 log_error("failed to chown '%s' %u %u ", device_node, uid, gid);
2670 return -errno;
2671 } else
2672 log_debug("chown '%s' %u %u", device_node, uid, gid);
2673 }
2674
2675 utimensat(AT_FDCWD, device_node, NULL, 0);
2676 break;
2677 }
2678 case TK_END:
2679 goto finish;
2680 }
2681
2682 cur++;
2683 continue;
2684 next:
2685 /* fast-forward to next rule */
2686 cur = rule + rule->rule.token_count;
2687 continue;
2688 }
2689
2690 finish:
2691 if (f) {
2692 fflush(f);
2693 fchmod(fileno(f), 0644);
2694 if (ferror(f) || rename(path, "/run/udev/static_node-tags") < 0) {
2695 r = -errno;
2696 unlink("/run/udev/static_node-tags");
2697 unlink(path);
2698 }
2699 fclose(f);
2700 }
2701
2702 return r;
2703 }