Line data Source code
1 : /* SPDX-License-Identifier: GPL-2.0+ */
2 :
3 : #include <ctype.h>
4 : #include <errno.h>
5 : #include <fcntl.h>
6 : #include <net/if.h>
7 : #include <stddef.h>
8 : #include <stdio.h>
9 : #include <stdlib.h>
10 : #include <sys/wait.h>
11 : #include <unistd.h>
12 :
13 : #include "sd-event.h"
14 :
15 : #include "alloc-util.h"
16 : #include "device-private.h"
17 : #include "device-util.h"
18 : #include "fd-util.h"
19 : #include "fs-util.h"
20 : #include "format-util.h"
21 : #include "libudev-util.h"
22 : #include "netlink-util.h"
23 : #include "parse-util.h"
24 : #include "path-util.h"
25 : #include "process-util.h"
26 : #include "rlimit-util.h"
27 : #include "signal-util.h"
28 : #include "stdio-util.h"
29 : #include "string-util.h"
30 : #include "strv.h"
31 : #include "strxcpyx.h"
32 : #include "udev-builtin.h"
33 : #include "udev-event.h"
34 : #include "udev-node.h"
35 : #include "udev-util.h"
36 : #include "udev-watch.h"
37 : #include "user-util.h"
38 :
39 : typedef struct Spawn {
40 : sd_device *device;
41 : const char *cmd;
42 : pid_t pid;
43 : usec_t timeout_warn_usec;
44 : usec_t timeout_usec;
45 : usec_t event_birth_usec;
46 : bool accept_failure;
47 : int fd_stdout;
48 : int fd_stderr;
49 : char *result;
50 : size_t result_size;
51 : size_t result_len;
52 : } Spawn;
53 :
54 0 : UdevEvent *udev_event_new(sd_device *dev, usec_t exec_delay_usec, sd_netlink *rtnl) {
55 : UdevEvent *event;
56 :
57 0 : assert(dev);
58 :
59 0 : event = new(UdevEvent, 1);
60 0 : if (!event)
61 0 : return NULL;
62 :
63 0 : *event = (UdevEvent) {
64 0 : .dev = sd_device_ref(dev),
65 0 : .birth_usec = now(CLOCK_MONOTONIC),
66 : .exec_delay_usec = exec_delay_usec,
67 0 : .rtnl = sd_netlink_ref(rtnl),
68 : .uid = UID_INVALID,
69 : .gid = GID_INVALID,
70 : .mode = MODE_INVALID,
71 : };
72 :
73 0 : return event;
74 : }
75 :
76 0 : UdevEvent *udev_event_free(UdevEvent *event) {
77 0 : if (!event)
78 0 : return NULL;
79 :
80 0 : sd_device_unref(event->dev);
81 0 : sd_device_unref(event->dev_db_clone);
82 0 : sd_netlink_unref(event->rtnl);
83 0 : ordered_hashmap_free_free_key(event->run_list);
84 0 : ordered_hashmap_free_free_free(event->seclabel_list);
85 0 : free(event->program_result);
86 0 : free(event->name);
87 :
88 0 : return mfree(event);
89 : }
90 :
91 : typedef enum {
92 : FORMAT_SUBST_DEVNODE,
93 : FORMAT_SUBST_ATTR,
94 : FORMAT_SUBST_ENV,
95 : FORMAT_SUBST_KERNEL,
96 : FORMAT_SUBST_KERNEL_NUMBER,
97 : FORMAT_SUBST_DRIVER,
98 : FORMAT_SUBST_DEVPATH,
99 : FORMAT_SUBST_ID,
100 : FORMAT_SUBST_MAJOR,
101 : FORMAT_SUBST_MINOR,
102 : FORMAT_SUBST_RESULT,
103 : FORMAT_SUBST_PARENT,
104 : FORMAT_SUBST_NAME,
105 : FORMAT_SUBST_LINKS,
106 : FORMAT_SUBST_ROOT,
107 : FORMAT_SUBST_SYS,
108 : _FORMAT_SUBST_TYPE_MAX,
109 : _FORMAT_SUBST_TYPE_INVALID = -1
110 : } FormatSubstitutionType;
111 :
112 : struct subst_map_entry {
113 : const char *name;
114 : const char fmt;
115 : FormatSubstitutionType type;
116 : };
117 :
118 : static const struct subst_map_entry map[] = {
119 : { .name = "devnode", .fmt = 'N', .type = FORMAT_SUBST_DEVNODE },
120 : { .name = "tempnode", .fmt = 'N', .type = FORMAT_SUBST_DEVNODE }, /* deprecated */
121 : { .name = "attr", .fmt = 's', .type = FORMAT_SUBST_ATTR },
122 : { .name = "sysfs", .fmt = 's', .type = FORMAT_SUBST_ATTR }, /* deprecated */
123 : { .name = "env", .fmt = 'E', .type = FORMAT_SUBST_ENV },
124 : { .name = "kernel", .fmt = 'k', .type = FORMAT_SUBST_KERNEL },
125 : { .name = "number", .fmt = 'n', .type = FORMAT_SUBST_KERNEL_NUMBER },
126 : { .name = "driver", .fmt = 'd', .type = FORMAT_SUBST_DRIVER },
127 : { .name = "devpath", .fmt = 'p', .type = FORMAT_SUBST_DEVPATH },
128 : { .name = "id", .fmt = 'b', .type = FORMAT_SUBST_ID },
129 : { .name = "major", .fmt = 'M', .type = FORMAT_SUBST_MAJOR },
130 : { .name = "minor", .fmt = 'm', .type = FORMAT_SUBST_MINOR },
131 : { .name = "result", .fmt = 'c', .type = FORMAT_SUBST_RESULT },
132 : { .name = "parent", .fmt = 'P', .type = FORMAT_SUBST_PARENT },
133 : { .name = "name", .fmt = 'D', .type = FORMAT_SUBST_NAME },
134 : { .name = "links", .fmt = 'L', .type = FORMAT_SUBST_LINKS },
135 : { .name = "root", .fmt = 'r', .type = FORMAT_SUBST_ROOT },
136 : { .name = "sys", .fmt = 'S', .type = FORMAT_SUBST_SYS },
137 : };
138 :
139 0 : static const char *format_type_to_string(FormatSubstitutionType t) {
140 0 : for (size_t i = 0; i < ELEMENTSOF(map); i++)
141 0 : if (map[i].type == t)
142 0 : return map[i].name;
143 0 : return NULL;
144 : }
145 :
146 0 : static char format_type_to_char(FormatSubstitutionType t) {
147 0 : for (size_t i = 0; i < ELEMENTSOF(map); i++)
148 0 : if (map[i].type == t)
149 0 : return map[i].fmt;
150 0 : return '\0';
151 : }
152 :
153 0 : static int get_subst_type(const char **str, bool strict, FormatSubstitutionType *ret_type, char ret_attr[static UTIL_PATH_SIZE]) {
154 0 : const char *p = *str, *q = NULL;
155 : size_t i;
156 :
157 0 : assert(str);
158 0 : assert(*str);
159 0 : assert(ret_type);
160 0 : assert(ret_attr);
161 :
162 0 : if (*p == '$') {
163 0 : p++;
164 0 : if (*p == '$') {
165 0 : *str = p;
166 0 : return 0;
167 : }
168 0 : for (i = 0; i < ELEMENTSOF(map); i++)
169 0 : if ((q = startswith(p, map[i].name)))
170 0 : break;
171 0 : } else if (*p == '%') {
172 0 : p++;
173 0 : if (*p == '%') {
174 0 : *str = p;
175 0 : return 0;
176 : }
177 :
178 0 : for (i = 0; i < ELEMENTSOF(map); i++)
179 0 : if (*p == map[i].fmt) {
180 0 : q = p + 1;
181 0 : break;
182 : }
183 : } else
184 0 : return 0;
185 0 : if (!q)
186 : /* When 'strict' flag is set, then '$' and '%' must be escaped. */
187 0 : return strict ? -EINVAL : 0;
188 :
189 0 : if (*q == '{') {
190 : const char *start, *end;
191 : size_t len;
192 :
193 0 : start = q + 1;
194 0 : end = strchr(start, '}');
195 0 : if (!end)
196 0 : return -EINVAL;
197 :
198 0 : len = end - start;
199 0 : if (len == 0 || len >= UTIL_PATH_SIZE)
200 0 : return -EINVAL;
201 :
202 0 : strnscpy(ret_attr, UTIL_PATH_SIZE, start, len);
203 0 : q = end + 1;
204 : } else
205 0 : *ret_attr = '\0';
206 :
207 0 : *str = q;
208 0 : *ret_type = map[i].type;
209 0 : return 1;
210 : }
211 :
212 0 : static int safe_atou_optional_plus(const char *s, unsigned *ret) {
213 : const char *p;
214 : int r;
215 :
216 0 : assert(s);
217 0 : assert(ret);
218 :
219 : /* Returns 1 if plus, 0 if no plus, negative on error */
220 :
221 0 : p = endswith(s, "+");
222 0 : if (p)
223 0 : s = strndupa(s, p - s);
224 :
225 0 : r = safe_atou(s, ret);
226 0 : if (r < 0)
227 0 : return r;
228 :
229 0 : return !!p;
230 : }
231 :
232 0 : static ssize_t udev_event_subst_format(
233 : UdevEvent *event,
234 : FormatSubstitutionType type,
235 : const char *attr,
236 : char *dest,
237 : size_t l) {
238 0 : sd_device *parent, *dev = event->dev;
239 0 : const char *val = NULL;
240 0 : char *s = dest;
241 : int r;
242 :
243 0 : switch (type) {
244 0 : case FORMAT_SUBST_DEVPATH:
245 0 : r = sd_device_get_devpath(dev, &val);
246 0 : if (r < 0)
247 0 : return r;
248 0 : l = strpcpy(&s, l, val);
249 0 : break;
250 0 : case FORMAT_SUBST_KERNEL:
251 0 : r = sd_device_get_sysname(dev, &val);
252 0 : if (r < 0)
253 0 : return r;
254 0 : l = strpcpy(&s, l, val);
255 0 : break;
256 0 : case FORMAT_SUBST_KERNEL_NUMBER:
257 0 : r = sd_device_get_sysnum(dev, &val);
258 0 : if (r == -ENOENT)
259 0 : goto null_terminate;
260 0 : if (r < 0)
261 0 : return r;
262 0 : l = strpcpy(&s, l, val);
263 0 : break;
264 0 : case FORMAT_SUBST_ID:
265 0 : if (!event->dev_parent)
266 0 : goto null_terminate;
267 0 : r = sd_device_get_sysname(event->dev_parent, &val);
268 0 : if (r < 0)
269 0 : return r;
270 0 : l = strpcpy(&s, l, val);
271 0 : break;
272 0 : case FORMAT_SUBST_DRIVER:
273 0 : if (!event->dev_parent)
274 0 : goto null_terminate;
275 0 : r = sd_device_get_driver(event->dev_parent, &val);
276 0 : if (r == -ENOENT)
277 0 : goto null_terminate;
278 0 : if (r < 0)
279 0 : return r;
280 0 : l = strpcpy(&s, l, val);
281 0 : break;
282 0 : case FORMAT_SUBST_MAJOR:
283 : case FORMAT_SUBST_MINOR: {
284 : dev_t devnum;
285 :
286 0 : r = sd_device_get_devnum(dev, &devnum);
287 0 : if (r < 0 && r != -ENOENT)
288 0 : return r;
289 0 : l = strpcpyf(&s, l, "%u", r < 0 ? 0 : type == FORMAT_SUBST_MAJOR ? major(devnum) : minor(devnum));
290 0 : break;
291 : }
292 0 : case FORMAT_SUBST_RESULT: {
293 0 : unsigned index = 0; /* 0 means whole string */
294 : bool has_plus;
295 :
296 0 : if (!event->program_result)
297 0 : goto null_terminate;
298 :
299 0 : if (!isempty(attr)) {
300 0 : r = safe_atou_optional_plus(attr, &index);
301 0 : if (r < 0)
302 0 : return r;
303 :
304 0 : has_plus = r;
305 : }
306 :
307 0 : if (index == 0)
308 0 : l = strpcpy(&s, l, event->program_result);
309 : else {
310 : const char *start, *p;
311 : unsigned i;
312 :
313 0 : p = skip_leading_chars(event->program_result, NULL);
314 :
315 0 : for (i = 1; i < index; i++) {
316 0 : while (*p && !strchr(WHITESPACE, *p))
317 0 : p++;
318 0 : p = skip_leading_chars(p, NULL);
319 0 : if (*p == '\0')
320 0 : break;
321 : }
322 0 : if (i != index) {
323 0 : log_device_debug(dev, "requested part of result string not found");
324 0 : goto null_terminate;
325 : }
326 :
327 0 : start = p;
328 : /* %c{2+} copies the whole string from the second part on */
329 0 : if (has_plus)
330 0 : l = strpcpy(&s, l, start);
331 : else {
332 0 : while (*p && !strchr(WHITESPACE, *p))
333 0 : p++;
334 0 : l = strnpcpy(&s, l, start, p - start);
335 : }
336 : }
337 0 : break;
338 : }
339 0 : case FORMAT_SUBST_ATTR: {
340 : char vbuf[UTIL_NAME_SIZE];
341 : int count;
342 :
343 0 : if (isempty(attr))
344 0 : return -EINVAL;
345 :
346 : /* try to read the value specified by "[dmi/id]product_name" */
347 0 : if (util_resolve_subsys_kernel(attr, vbuf, sizeof(vbuf), true) == 0)
348 0 : val = vbuf;
349 :
350 : /* try to read the attribute the device */
351 0 : if (!val)
352 0 : (void) sd_device_get_sysattr_value(dev, attr, &val);
353 :
354 : /* try to read the attribute of the parent device, other matches have selected */
355 0 : if (!val && event->dev_parent && event->dev_parent != dev)
356 0 : (void) sd_device_get_sysattr_value(event->dev_parent, attr, &val);
357 :
358 0 : if (!val)
359 0 : goto null_terminate;
360 :
361 : /* strip trailing whitespace, and replace unwanted characters */
362 0 : if (val != vbuf)
363 0 : strscpy(vbuf, sizeof(vbuf), val);
364 0 : delete_trailing_chars(vbuf, NULL);
365 0 : count = util_replace_chars(vbuf, UDEV_ALLOWED_CHARS_INPUT);
366 0 : if (count > 0)
367 0 : log_device_debug(dev, "%i character(s) replaced", count);
368 0 : l = strpcpy(&s, l, vbuf);
369 0 : break;
370 : }
371 0 : case FORMAT_SUBST_PARENT:
372 0 : r = sd_device_get_parent(dev, &parent);
373 0 : if (r == -ENODEV)
374 0 : goto null_terminate;
375 0 : if (r < 0)
376 0 : return r;
377 0 : r = sd_device_get_devname(parent, &val);
378 0 : if (r == -ENOENT)
379 0 : goto null_terminate;
380 0 : if (r < 0)
381 0 : return r;
382 0 : l = strpcpy(&s, l, val + STRLEN("/dev/"));
383 0 : break;
384 0 : case FORMAT_SUBST_DEVNODE:
385 0 : r = sd_device_get_devname(dev, &val);
386 0 : if (r == -ENOENT)
387 0 : goto null_terminate;
388 0 : if (r < 0)
389 0 : return r;
390 0 : l = strpcpy(&s, l, val);
391 0 : break;
392 0 : case FORMAT_SUBST_NAME:
393 0 : if (event->name)
394 0 : l = strpcpy(&s, l, event->name);
395 0 : else if (sd_device_get_devname(dev, &val) >= 0)
396 0 : l = strpcpy(&s, l, val + STRLEN("/dev/"));
397 : else {
398 0 : r = sd_device_get_sysname(dev, &val);
399 0 : if (r < 0)
400 0 : return r;
401 0 : l = strpcpy(&s, l, val);
402 : }
403 0 : break;
404 0 : case FORMAT_SUBST_LINKS:
405 0 : FOREACH_DEVICE_DEVLINK(dev, val)
406 0 : if (s == dest)
407 0 : l = strpcpy(&s, l, val + STRLEN("/dev/"));
408 : else
409 0 : l = strpcpyl(&s, l, " ", val + STRLEN("/dev/"), NULL);
410 0 : if (s == dest)
411 0 : goto null_terminate;
412 0 : break;
413 0 : case FORMAT_SUBST_ROOT:
414 0 : l = strpcpy(&s, l, "/dev");
415 0 : break;
416 0 : case FORMAT_SUBST_SYS:
417 0 : l = strpcpy(&s, l, "/sys");
418 0 : break;
419 0 : case FORMAT_SUBST_ENV:
420 0 : if (isempty(attr))
421 0 : return -EINVAL;
422 0 : r = sd_device_get_property_value(dev, attr, &val);
423 0 : if (r == -ENOENT)
424 0 : goto null_terminate;
425 0 : if (r < 0)
426 0 : return r;
427 0 : l = strpcpy(&s, l, val);
428 0 : break;
429 0 : default:
430 0 : assert_not_reached("Unknown format substitution type");
431 : }
432 :
433 0 : return s - dest;
434 :
435 0 : null_terminate:
436 0 : *s = '\0';
437 0 : return 0;
438 : }
439 :
440 0 : ssize_t udev_event_apply_format(UdevEvent *event,
441 : const char *src, char *dest, size_t size,
442 : bool replace_whitespace) {
443 0 : const char *s = src;
444 : int r;
445 :
446 0 : assert(event);
447 0 : assert(event->dev);
448 0 : assert(src);
449 0 : assert(dest);
450 0 : assert(size > 0);
451 :
452 0 : while (*s) {
453 : FormatSubstitutionType type;
454 : char attr[UTIL_PATH_SIZE];
455 : ssize_t subst_len;
456 :
457 0 : r = get_subst_type(&s, false, &type, attr);
458 0 : if (r < 0)
459 0 : return log_device_warning_errno(event->dev, r, "Invalid format string, ignoring: %s", src);
460 0 : if (r == 0) {
461 0 : if (size < 2) /* need space for this char and the terminating NUL */
462 0 : break;
463 0 : *dest++ = *s++;
464 0 : size--;
465 0 : continue;
466 : }
467 :
468 0 : subst_len = udev_event_subst_format(event, type, attr, dest, size);
469 0 : if (subst_len < 0)
470 0 : return log_device_warning_errno(event->dev, subst_len,
471 : "Failed to substitute variable '$%s' or apply format '%%%c', ignoring: %m",
472 : format_type_to_string(type), format_type_to_char(type));
473 :
474 : /* FORMAT_SUBST_RESULT handles spaces itself */
475 0 : if (replace_whitespace && type != FORMAT_SUBST_RESULT)
476 : /* util_replace_whitespace can replace in-place,
477 : * and does nothing if subst_len == 0 */
478 0 : subst_len = util_replace_whitespace(dest, dest, subst_len);
479 :
480 0 : dest += subst_len;
481 0 : size -= subst_len;
482 : }
483 :
484 0 : assert(size >= 1);
485 0 : *dest = '\0';
486 0 : return size;
487 : }
488 :
489 0 : int udev_check_format(const char *value, size_t *offset, const char **hint) {
490 : FormatSubstitutionType type;
491 0 : const char *s = value;
492 : char attr[UTIL_PATH_SIZE];
493 : int r;
494 :
495 0 : while (*s) {
496 0 : r = get_subst_type(&s, true, &type, attr);
497 0 : if (r < 0) {
498 0 : if (offset)
499 0 : *offset = s - value;
500 0 : if (hint)
501 0 : *hint = "invalid substitution type";
502 0 : return r;
503 0 : } else if (r == 0) {
504 0 : s++;
505 0 : continue;
506 : }
507 :
508 0 : if (IN_SET(type, FORMAT_SUBST_ATTR, FORMAT_SUBST_ENV) && isempty(attr)) {
509 0 : if (offset)
510 0 : *offset = s - value;
511 0 : if (hint)
512 0 : *hint = "attribute value missing";
513 0 : return -EINVAL;
514 : }
515 :
516 0 : if (type == FORMAT_SUBST_RESULT && !isempty(attr)) {
517 : unsigned i;
518 :
519 0 : r = safe_atou_optional_plus(attr, &i);
520 0 : if (r < 0) {
521 0 : if (offset)
522 0 : *offset = s - value;
523 0 : if (hint)
524 0 : *hint = "attribute value not a valid number";
525 0 : return r;
526 : }
527 : }
528 : }
529 :
530 0 : return 0;
531 : }
532 :
533 0 : static int on_spawn_io(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
534 0 : Spawn *spawn = userdata;
535 : char buf[4096], *p;
536 : size_t size;
537 : ssize_t l;
538 :
539 0 : assert(spawn);
540 0 : assert(fd == spawn->fd_stdout || fd == spawn->fd_stderr);
541 0 : assert(!spawn->result || spawn->result_len < spawn->result_size);
542 :
543 0 : if (fd == spawn->fd_stdout && spawn->result) {
544 0 : p = spawn->result + spawn->result_len;
545 0 : size = spawn->result_size - spawn->result_len;
546 : } else {
547 0 : p = buf;
548 0 : size = sizeof(buf);
549 : }
550 :
551 0 : l = read(fd, p, size - 1);
552 0 : if (l < 0) {
553 0 : if (errno != EAGAIN)
554 0 : log_device_error_errno(spawn->device, errno,
555 : "Failed to read stdout of '%s': %m", spawn->cmd);
556 :
557 0 : return 0;
558 : }
559 :
560 0 : p[l] = '\0';
561 0 : if (fd == spawn->fd_stdout && spawn->result)
562 0 : spawn->result_len += l;
563 :
564 : /* Log output only if we watch stderr. */
565 0 : if (l > 0 && spawn->fd_stderr >= 0) {
566 0 : _cleanup_strv_free_ char **v = NULL;
567 : char **q;
568 :
569 0 : v = strv_split_newlines(p);
570 0 : if (!v)
571 0 : return 0;
572 :
573 0 : STRV_FOREACH(q, v)
574 0 : log_device_debug(spawn->device, "'%s'(%s) '%s'", spawn->cmd,
575 : fd == spawn->fd_stdout ? "out" : "err", *q);
576 : }
577 :
578 0 : return 0;
579 : }
580 :
581 0 : static int on_spawn_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
582 0 : Spawn *spawn = userdata;
583 : char timeout[FORMAT_TIMESPAN_MAX];
584 :
585 0 : assert(spawn);
586 :
587 0 : kill_and_sigcont(spawn->pid, SIGKILL);
588 :
589 0 : log_device_error(spawn->device, "Spawned process '%s' ["PID_FMT"] timed out after %s, killing",
590 : spawn->cmd, spawn->pid,
591 : format_timespan(timeout, sizeof(timeout), spawn->timeout_usec, USEC_PER_SEC));
592 :
593 0 : return 1;
594 : }
595 :
596 0 : static int on_spawn_timeout_warning(sd_event_source *s, uint64_t usec, void *userdata) {
597 0 : Spawn *spawn = userdata;
598 : char timeout[FORMAT_TIMESPAN_MAX];
599 :
600 0 : assert(spawn);
601 :
602 0 : log_device_warning(spawn->device, "Spawned process '%s' ["PID_FMT"] is taking longer than %s to complete",
603 : spawn->cmd, spawn->pid,
604 : format_timespan(timeout, sizeof(timeout), spawn->timeout_warn_usec, USEC_PER_SEC));
605 :
606 0 : return 1;
607 : }
608 :
609 0 : static int on_spawn_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata) {
610 0 : Spawn *spawn = userdata;
611 0 : int ret = -EIO;
612 :
613 0 : assert(spawn);
614 :
615 0 : switch (si->si_code) {
616 0 : case CLD_EXITED:
617 0 : if (si->si_status == 0)
618 0 : log_device_debug(spawn->device, "Process '%s' succeeded.", spawn->cmd);
619 : else
620 0 : log_device_full(spawn->device, spawn->accept_failure ? LOG_DEBUG : LOG_WARNING, 0,
621 : "Process '%s' failed with exit code %i.", spawn->cmd, si->si_status);
622 0 : ret = si->si_status;
623 0 : break;
624 0 : case CLD_KILLED:
625 : case CLD_DUMPED:
626 0 : log_device_error(spawn->device, "Process '%s' terminated by signal %s.", spawn->cmd, signal_to_string(si->si_status));
627 0 : break;
628 0 : default:
629 0 : log_device_error(spawn->device, "Process '%s' failed due to unknown reason.", spawn->cmd);
630 : }
631 :
632 0 : sd_event_exit(sd_event_source_get_event(s), ret);
633 0 : return 1;
634 : }
635 :
636 0 : static int spawn_wait(Spawn *spawn) {
637 0 : _cleanup_(sd_event_unrefp) sd_event *e = NULL;
638 : int r;
639 :
640 0 : assert(spawn);
641 :
642 0 : r = sd_event_new(&e);
643 0 : if (r < 0)
644 0 : return r;
645 :
646 0 : if (spawn->timeout_usec > 0) {
647 : usec_t usec, age_usec;
648 :
649 0 : usec = now(CLOCK_MONOTONIC);
650 0 : age_usec = usec - spawn->event_birth_usec;
651 0 : if (age_usec < spawn->timeout_usec) {
652 0 : if (spawn->timeout_warn_usec > 0 &&
653 0 : spawn->timeout_warn_usec < spawn->timeout_usec &&
654 0 : spawn->timeout_warn_usec > age_usec) {
655 0 : spawn->timeout_warn_usec -= age_usec;
656 :
657 0 : r = sd_event_add_time(e, NULL, CLOCK_MONOTONIC,
658 0 : usec + spawn->timeout_warn_usec, USEC_PER_SEC,
659 : on_spawn_timeout_warning, spawn);
660 0 : if (r < 0)
661 0 : return r;
662 : }
663 :
664 0 : spawn->timeout_usec -= age_usec;
665 :
666 0 : r = sd_event_add_time(e, NULL, CLOCK_MONOTONIC,
667 0 : usec + spawn->timeout_usec, USEC_PER_SEC, on_spawn_timeout, spawn);
668 0 : if (r < 0)
669 0 : return r;
670 : }
671 : }
672 :
673 0 : if (spawn->fd_stdout >= 0) {
674 0 : r = sd_event_add_io(e, NULL, spawn->fd_stdout, EPOLLIN, on_spawn_io, spawn);
675 0 : if (r < 0)
676 0 : return r;
677 : }
678 :
679 0 : if (spawn->fd_stderr >= 0) {
680 0 : r = sd_event_add_io(e, NULL, spawn->fd_stderr, EPOLLIN, on_spawn_io, spawn);
681 0 : if (r < 0)
682 0 : return r;
683 : }
684 :
685 0 : r = sd_event_add_child(e, NULL, spawn->pid, WEXITED, on_spawn_sigchld, spawn);
686 0 : if (r < 0)
687 0 : return r;
688 :
689 0 : return sd_event_loop(e);
690 : }
691 :
692 0 : int udev_event_spawn(UdevEvent *event,
693 : usec_t timeout_usec,
694 : bool accept_failure,
695 : const char *cmd,
696 : char *result, size_t ressize) {
697 0 : _cleanup_close_pair_ int outpipe[2] = {-1, -1}, errpipe[2] = {-1, -1};
698 0 : _cleanup_strv_free_ char **argv = NULL;
699 0 : char **envp = NULL;
700 : Spawn spawn;
701 : pid_t pid;
702 : int r;
703 :
704 0 : assert(event);
705 0 : assert(event->dev);
706 0 : assert(result || ressize == 0);
707 :
708 : /* pipes from child to parent */
709 0 : if (result || log_get_max_level() >= LOG_INFO)
710 0 : if (pipe2(outpipe, O_NONBLOCK|O_CLOEXEC) != 0)
711 0 : return log_device_error_errno(event->dev, errno,
712 : "Failed to create pipe for command '%s': %m", cmd);
713 :
714 0 : if (log_get_max_level() >= LOG_INFO)
715 0 : if (pipe2(errpipe, O_NONBLOCK|O_CLOEXEC) != 0)
716 0 : return log_device_error_errno(event->dev, errno,
717 : "Failed to create pipe for command '%s': %m", cmd);
718 :
719 0 : argv = strv_split_full(cmd, NULL, SPLIT_QUOTES|SPLIT_RELAX);
720 0 : if (!argv)
721 0 : return log_oom();
722 :
723 0 : if (isempty(argv[0]))
724 0 : return log_device_error_errno(event->dev, SYNTHETIC_ERRNO(EINVAL),
725 : "Invalid command '%s'", cmd);
726 :
727 : /* allow programs in /usr/lib/udev/ to be called without the path */
728 0 : if (!path_is_absolute(argv[0])) {
729 : char *program;
730 :
731 0 : program = path_join(UDEVLIBEXECDIR, argv[0]);
732 0 : if (!program)
733 0 : return log_oom();
734 :
735 0 : free_and_replace(argv[0], program);
736 : }
737 :
738 0 : r = device_get_properties_strv(event->dev, &envp);
739 0 : if (r < 0)
740 0 : return log_device_error_errno(event->dev, r, "Failed to get device properties");
741 :
742 0 : log_device_debug(event->dev, "Starting '%s'", cmd);
743 :
744 0 : r = safe_fork("(spawn)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
745 0 : if (r < 0)
746 0 : return log_device_error_errno(event->dev, r,
747 : "Failed to fork() to execute command '%s': %m", cmd);
748 0 : if (r == 0) {
749 0 : if (rearrange_stdio(-1, outpipe[WRITE_END], errpipe[WRITE_END]) < 0)
750 0 : _exit(EXIT_FAILURE);
751 :
752 0 : (void) close_all_fds(NULL, 0);
753 0 : (void) rlimit_nofile_safe();
754 :
755 0 : execve(argv[0], argv, envp);
756 0 : _exit(EXIT_FAILURE);
757 : }
758 :
759 : /* parent closed child's ends of pipes */
760 0 : outpipe[WRITE_END] = safe_close(outpipe[WRITE_END]);
761 0 : errpipe[WRITE_END] = safe_close(errpipe[WRITE_END]);
762 :
763 0 : spawn = (Spawn) {
764 0 : .device = event->dev,
765 : .cmd = cmd,
766 : .pid = pid,
767 : .accept_failure = accept_failure,
768 0 : .timeout_warn_usec = udev_warn_timeout(timeout_usec),
769 : .timeout_usec = timeout_usec,
770 0 : .event_birth_usec = event->birth_usec,
771 0 : .fd_stdout = outpipe[READ_END],
772 0 : .fd_stderr = errpipe[READ_END],
773 : .result = result,
774 : .result_size = ressize,
775 : };
776 0 : r = spawn_wait(&spawn);
777 0 : if (r < 0)
778 0 : return log_device_error_errno(event->dev, r,
779 : "Failed to wait for spawned command '%s': %m", cmd);
780 :
781 0 : if (result)
782 0 : result[spawn.result_len] = '\0';
783 :
784 0 : return r; /* 0 for success, and positive if the program failed */
785 : }
786 :
787 0 : static int rename_netif(UdevEvent *event) {
788 0 : sd_device *dev = event->dev;
789 : const char *oldname;
790 : int ifindex, r;
791 :
792 0 : if (!event->name)
793 0 : return 0; /* No new name is requested. */
794 :
795 0 : r = sd_device_get_sysname(dev, &oldname);
796 0 : if (r < 0)
797 0 : return log_device_error_errno(dev, r, "Failed to get sysname: %m");
798 :
799 0 : if (streq(event->name, oldname))
800 0 : return 0; /* The interface name is already requested name. */
801 :
802 0 : if (!device_for_action(dev, DEVICE_ACTION_ADD))
803 0 : return 0; /* Rename the interface only when it is added. */
804 :
805 0 : r = sd_device_get_ifindex(dev, &ifindex);
806 0 : if (r == -ENOENT)
807 0 : return 0; /* Device is not a network interface. */
808 0 : if (r < 0)
809 0 : return log_device_error_errno(dev, r, "Failed to get ifindex: %m");
810 :
811 0 : r = rtnl_set_link_name(&event->rtnl, ifindex, event->name);
812 0 : if (r < 0)
813 0 : return log_device_error_errno(dev, r, "Failed to rename network interface %i from '%s' to '%s': %m",
814 : ifindex, oldname, event->name);
815 :
816 : /* Set ID_RENAMING boolean property here, and drop it in the corresponding move uevent later. */
817 0 : r = device_add_property(dev, "ID_RENAMING", "1");
818 0 : if (r < 0)
819 0 : return log_device_warning_errno(dev, r, "Failed to add 'ID_RENAMING' property: %m");
820 :
821 0 : r = device_rename(dev, event->name);
822 0 : if (r < 0)
823 0 : return log_device_warning_errno(dev, r, "Failed to update properties with new name '%s': %m", event->name);
824 :
825 0 : log_device_debug(dev, "Network interface %i is renamed from '%s' to '%s'", ifindex, oldname, event->name);
826 :
827 0 : return 1;
828 : }
829 :
830 0 : static int update_devnode(UdevEvent *event) {
831 0 : sd_device *dev = event->dev;
832 : int r;
833 :
834 0 : r = sd_device_get_devnum(dev, NULL);
835 0 : if (r == -ENOENT)
836 0 : return 0;
837 0 : if (r < 0)
838 0 : return log_device_error_errno(dev, r, "Failed to get devnum: %m");
839 :
840 : /* remove/update possible left-over symlinks from old database entry */
841 0 : if (event->dev_db_clone)
842 0 : (void) udev_node_update_old_links(dev, event->dev_db_clone);
843 :
844 0 : if (!uid_is_valid(event->uid)) {
845 0 : r = device_get_devnode_uid(dev, &event->uid);
846 0 : if (r < 0 && r != -ENOENT)
847 0 : return log_device_error_errno(dev, r, "Failed to get devnode UID: %m");
848 : }
849 :
850 0 : if (!gid_is_valid(event->gid)) {
851 0 : r = device_get_devnode_gid(dev, &event->gid);
852 0 : if (r < 0 && r != -ENOENT)
853 0 : return log_device_error_errno(dev, r, "Failed to get devnode GID: %m");
854 : }
855 :
856 0 : if (event->mode == MODE_INVALID) {
857 0 : r = device_get_devnode_mode(dev, &event->mode);
858 0 : if (r < 0 && r != -ENOENT)
859 0 : return log_device_error_errno(dev, r, "Failed to get devnode mode: %m");
860 : }
861 0 : if (event->mode == MODE_INVALID && gid_is_valid(event->gid) && event->gid > 0)
862 : /* If group is set, but mode is not set, "upgrade" mode for the group. */
863 0 : event->mode = 0660;
864 :
865 0 : bool apply_mac = device_for_action(dev, DEVICE_ACTION_ADD);
866 :
867 0 : return udev_node_add(dev, apply_mac, event->mode, event->uid, event->gid, event->seclabel_list);
868 : }
869 :
870 0 : static void event_execute_rules_on_remove(
871 : UdevEvent *event,
872 : usec_t timeout_usec,
873 : Hashmap *properties_list,
874 : UdevRules *rules) {
875 :
876 0 : sd_device *dev = event->dev;
877 : int r;
878 :
879 0 : r = device_read_db_internal(dev, true);
880 0 : if (r < 0)
881 0 : log_device_debug_errno(dev, r, "Failed to read database under /run/udev/data/: %m");
882 :
883 0 : r = device_tag_index(dev, NULL, false);
884 0 : if (r < 0)
885 0 : log_device_debug_errno(dev, r, "Failed to remove corresponding tag files under /run/udev/tag/, ignoring: %m");
886 :
887 0 : r = device_delete_db(dev);
888 0 : if (r < 0)
889 0 : log_device_debug_errno(dev, r, "Failed to delete database under /run/udev/data/, ignoring: %m");
890 :
891 0 : if (sd_device_get_devnum(dev, NULL) >= 0)
892 0 : (void) udev_watch_end(dev);
893 :
894 0 : (void) udev_rules_apply_to_event(rules, event, timeout_usec, properties_list);
895 :
896 0 : if (sd_device_get_devnum(dev, NULL) >= 0)
897 0 : (void) udev_node_remove(dev);
898 0 : }
899 :
900 0 : static int udev_event_on_move(UdevEvent *event) {
901 0 : sd_device *dev = event->dev;
902 : int r;
903 :
904 0 : if (event->dev_db_clone &&
905 0 : sd_device_get_devnum(dev, NULL) < 0) {
906 0 : r = device_copy_properties(dev, event->dev_db_clone);
907 0 : if (r < 0)
908 0 : log_device_debug_errno(dev, r, "Failed to copy properties from cloned sd_device object, ignoring: %m");
909 : }
910 :
911 : /* Drop previously added property */
912 0 : r = device_add_property(dev, "ID_RENAMING", NULL);
913 0 : if (r < 0)
914 0 : return log_device_debug_errno(dev, r, "Failed to remove 'ID_RENAMING' property: %m");
915 :
916 0 : return 0;
917 : }
918 :
919 0 : int udev_event_execute_rules(UdevEvent *event,
920 : usec_t timeout_usec,
921 : Hashmap *properties_list,
922 : UdevRules *rules) {
923 : const char *subsystem;
924 : DeviceAction action;
925 : sd_device *dev;
926 : int r;
927 :
928 0 : assert(event);
929 0 : assert(rules);
930 :
931 0 : dev = event->dev;
932 :
933 0 : r = sd_device_get_subsystem(dev, &subsystem);
934 0 : if (r < 0)
935 0 : return log_device_error_errno(dev, r, "Failed to get subsystem: %m");
936 :
937 0 : r = device_get_action(dev, &action);
938 0 : if (r < 0)
939 0 : return log_device_error_errno(dev, r, "Failed to get ACTION: %m");
940 :
941 0 : if (action == DEVICE_ACTION_REMOVE) {
942 0 : event_execute_rules_on_remove(event, timeout_usec, properties_list, rules);
943 0 : return 0;
944 : }
945 :
946 0 : r = device_clone_with_db(dev, &event->dev_db_clone);
947 0 : if (r < 0)
948 0 : return log_device_debug_errno(dev, r, "Failed to clone sd_device object: %m");
949 :
950 0 : if (event->dev_db_clone && sd_device_get_devnum(dev, NULL) >= 0)
951 : /* Disable watch during event processing. */
952 0 : (void) udev_watch_end(event->dev_db_clone);
953 :
954 0 : if (action == DEVICE_ACTION_MOVE) {
955 0 : r = udev_event_on_move(event);
956 0 : if (r < 0)
957 0 : return r;
958 : }
959 :
960 0 : r = udev_rules_apply_to_event(rules, event, timeout_usec, properties_list);
961 0 : if (r < 0)
962 0 : return log_device_debug_errno(dev, r, "Failed to apply udev rules: %m");
963 :
964 0 : r = rename_netif(event);
965 0 : if (r < 0)
966 0 : return r;
967 :
968 0 : r = update_devnode(event);
969 0 : if (r < 0)
970 0 : return r;
971 :
972 : /* preserve old, or get new initialization timestamp */
973 0 : r = device_ensure_usec_initialized(dev, event->dev_db_clone);
974 0 : if (r < 0)
975 0 : return log_device_debug_errno(dev, r, "Failed to set initialization timestamp: %m");
976 :
977 : /* (re)write database file */
978 0 : r = device_tag_index(dev, event->dev_db_clone, true);
979 0 : if (r < 0)
980 0 : return log_device_debug_errno(dev, r, "Failed to update tags under /run/udev/tag/: %m");
981 :
982 0 : r = device_update_db(dev);
983 0 : if (r < 0)
984 0 : return log_device_debug_errno(dev, r, "Failed to update database under /run/udev/data/: %m");
985 :
986 0 : device_set_is_initialized(dev);
987 :
988 0 : event->dev_db_clone = sd_device_unref(event->dev_db_clone);
989 :
990 0 : return 0;
991 : }
992 :
993 0 : void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec) {
994 : const char *command;
995 : void *val;
996 : Iterator i;
997 : int r;
998 :
999 0 : ORDERED_HASHMAP_FOREACH_KEY(val, command, event->run_list, i) {
1000 0 : UdevBuiltinCommand builtin_cmd = PTR_TO_UDEV_BUILTIN_CMD(val);
1001 :
1002 0 : if (builtin_cmd != _UDEV_BUILTIN_INVALID) {
1003 0 : log_device_debug(event->dev, "Running built-in command \"%s\"", command);
1004 0 : r = udev_builtin_run(event->dev, builtin_cmd, command, false);
1005 0 : if (r < 0)
1006 0 : log_device_debug_errno(event->dev, r, "Failed to run built-in command \"%s\", ignoring: %m", command);
1007 : } else {
1008 0 : if (event->exec_delay_usec > 0) {
1009 : char buf[FORMAT_TIMESPAN_MAX];
1010 :
1011 0 : log_device_debug(event->dev, "Delaying execution of \"%s\" for %s.",
1012 : command, format_timespan(buf, sizeof(buf), event->exec_delay_usec, USEC_PER_SEC));
1013 0 : (void) usleep(event->exec_delay_usec);
1014 : }
1015 :
1016 0 : log_device_debug(event->dev, "Running command \"%s\"", command);
1017 0 : r = udev_event_spawn(event, timeout_usec, false, command, NULL, 0);
1018 0 : if (r > 0) /* returned value is positive when program fails */
1019 0 : log_device_debug(event->dev, "Command \"%s\" returned %d (error), ignoring.", command, r);
1020 : }
1021 : }
1022 0 : }
|