]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/udev/udev-event.c
udev-event: set FORK_DEATHSIG flag
[thirdparty/systemd.git] / src / udev / udev-event.c
CommitLineData
e7145211 1/* SPDX-License-Identifier: GPL-2.0+ */
d46f37fd 2
d46f37fd 3#include <ctype.h>
07630cea
LP
4#include <errno.h>
5#include <fcntl.h>
959e8b5d 6#include <net/if.h>
0a6f50c0 7#include <poll.h>
07630cea
LP
8#include <stddef.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
2181d30a 12#include <sys/epoll.h>
07630cea 13#include <sys/prctl.h>
2181d30a 14#include <sys/signalfd.h>
07630cea
LP
15#include <sys/wait.h>
16#include <unistd.h>
d46f37fd 17
b5efdb8a 18#include "alloc-util.h"
3ffd4af2 19#include "fd-util.h"
f97b34a6 20#include "format-util.h"
70068602 21#include "libudev-device-internal.h"
07630cea 22#include "netlink-util.h"
feaa6db7 23#include "path-util.h"
8128f229 24#include "process-util.h"
24882e06 25#include "signal-util.h"
07630cea 26#include "string-util.h"
07a26e42 27#include "udev-builtin.h"
a2554ace 28#include "udev-node.h"
70068602 29#include "udev-watch.h"
24882e06 30#include "udev.h"
8128f229
TG
31
32typedef struct Spawn {
33 const char *cmd;
34 pid_t pid;
35 usec_t timeout_warn;
36 usec_t timeout;
53318514 37 bool accept_failure;
8128f229 38} Spawn;
d46f37fd 39
9ec6e95b 40struct udev_event *udev_event_new(struct udev_device *dev) {
912541b0
KS
41 struct udev_event *event;
42
955d98c9 43 event = new0(struct udev_event, 1);
912541b0
KS
44 if (event == NULL)
45 return NULL;
46 event->dev = dev;
3285baa8 47 event->birth_usec = now(CLOCK_MONOTONIC);
912541b0 48 return event;
aa8734ff
KS
49}
50
9ec6e95b 51void udev_event_unref(struct udev_event *event) {
29448498
YW
52 void *p;
53
912541b0
KS
54 if (event == NULL)
55 return;
1c4baffc 56 sd_netlink_unref(event->rtnl);
29448498
YW
57 while ((p = hashmap_steal_first_key(event->run_list)))
58 free(p);
d838e145 59 hashmap_free_free_free(event->seclabel_list);
912541b0
KS
60 free(event->program_result);
61 free(event->name);
912541b0 62 free(event);
aa8734ff
KS
63}
64
0d53705b
DS
65enum subst_type {
66 SUBST_UNKNOWN,
67 SUBST_DEVNODE,
68 SUBST_ATTR,
69 SUBST_ENV,
70 SUBST_KERNEL,
71 SUBST_KERNEL_NUMBER,
72 SUBST_DRIVER,
73 SUBST_DEVPATH,
74 SUBST_ID,
75 SUBST_MAJOR,
76 SUBST_MINOR,
77 SUBST_RESULT,
78 SUBST_PARENT,
79 SUBST_NAME,
80 SUBST_LINKS,
81 SUBST_ROOT,
82 SUBST_SYS,
83};
84
85static size_t subst_format_var(struct udev_event *event, struct udev_device *dev,
86 enum subst_type type, char *attr,
be452683
DS
87 char *dest, size_t l) {
88 char *s = dest;
0d53705b
DS
89
90 switch (type) {
91 case SUBST_DEVPATH:
92 l = strpcpy(&s, l, udev_device_get_devpath(dev));
93 break;
94 case SUBST_KERNEL:
95 l = strpcpy(&s, l, udev_device_get_sysname(dev));
96 break;
97 case SUBST_KERNEL_NUMBER:
98 if (udev_device_get_sysnum(dev) == NULL)
99 break;
100 l = strpcpy(&s, l, udev_device_get_sysnum(dev));
101 break;
102 case SUBST_ID:
103 if (event->dev_parent == NULL)
104 break;
105 l = strpcpy(&s, l, udev_device_get_sysname(event->dev_parent));
106 break;
107 case SUBST_DRIVER: {
108 const char *driver;
109
110 if (event->dev_parent == NULL)
111 break;
112
113 driver = udev_device_get_driver(event->dev_parent);
114 if (driver == NULL)
115 break;
116 l = strpcpy(&s, l, driver);
117 break;
118 }
119 case SUBST_MAJOR: {
120 char num[UTIL_PATH_SIZE];
121
122 sprintf(num, "%u", major(udev_device_get_devnum(dev)));
123 l = strpcpy(&s, l, num);
124 break;
125 }
126 case SUBST_MINOR: {
127 char num[UTIL_PATH_SIZE];
128
129 sprintf(num, "%u", minor(udev_device_get_devnum(dev)));
130 l = strpcpy(&s, l, num);
131 break;
132 }
133 case SUBST_RESULT: {
134 char *rest;
135 int i;
136
137 if (event->program_result == NULL)
138 break;
139 /* get part of the result string */
140 i = 0;
141 if (attr != NULL)
142 i = strtoul(attr, &rest, 10);
143 if (i > 0) {
144 char result[UTIL_PATH_SIZE];
145 char tmp[UTIL_PATH_SIZE];
146 char *cpos;
147
148 strscpy(result, sizeof(result), event->program_result);
149 cpos = result;
150 while (--i) {
151 while (cpos[0] != '\0' && !isspace(cpos[0]))
152 cpos++;
153 while (isspace(cpos[0]))
154 cpos++;
155 if (cpos[0] == '\0')
156 break;
157 }
158 if (i > 0) {
159 log_error("requested part of result string not found");
160 break;
161 }
162 strscpy(tmp, sizeof(tmp), cpos);
163 /* %{2+}c copies the whole string from the second part on */
164 if (rest[0] != '+') {
165 cpos = strchr(tmp, ' ');
166 if (cpos)
167 cpos[0] = '\0';
168 }
169 l = strpcpy(&s, l, tmp);
170 } else {
171 l = strpcpy(&s, l, event->program_result);
172 }
173 break;
174 }
175 case SUBST_ATTR: {
176 const char *value = NULL;
177 char vbuf[UTIL_NAME_SIZE];
178 size_t len;
179 int count;
180
181 if (attr == NULL) {
182 log_error("missing file parameter for attr");
183 break;
184 }
185
186 /* try to read the value specified by "[dmi/id]product_name" */
755c3fe9 187 if (util_resolve_subsys_kernel(attr, vbuf, sizeof(vbuf), 1) == 0)
0d53705b
DS
188 value = vbuf;
189
190 /* try to read the attribute the device */
191 if (value == NULL)
192 value = udev_device_get_sysattr_value(event->dev, attr);
193
194 /* try to read the attribute of the parent device, other matches have selected */
195 if (value == NULL && event->dev_parent != NULL && event->dev_parent != event->dev)
196 value = udev_device_get_sysattr_value(event->dev_parent, attr);
197
198 if (value == NULL)
199 break;
200
201 /* strip trailing whitespace, and replace unwanted characters */
202 if (value != vbuf)
203 strscpy(vbuf, sizeof(vbuf), value);
204 len = strlen(vbuf);
205 while (len > 0 && isspace(vbuf[--len]))
206 vbuf[len] = '\0';
207 count = util_replace_chars(vbuf, UDEV_ALLOWED_CHARS_INPUT);
208 if (count > 0)
209 log_debug("%i character(s) replaced" , count);
210 l = strpcpy(&s, l, vbuf);
211 break;
212 }
213 case SUBST_PARENT: {
214 struct udev_device *dev_parent;
215 const char *devnode;
216
217 dev_parent = udev_device_get_parent(event->dev);
218 if (dev_parent == NULL)
219 break;
220 devnode = udev_device_get_devnode(dev_parent);
221 if (devnode != NULL)
fbd0b64f 222 l = strpcpy(&s, l, devnode + STRLEN("/dev/"));
0d53705b
DS
223 break;
224 }
225 case SUBST_DEVNODE:
226 if (udev_device_get_devnode(dev) != NULL)
227 l = strpcpy(&s, l, udev_device_get_devnode(dev));
228 break;
229 case SUBST_NAME:
230 if (event->name != NULL)
231 l = strpcpy(&s, l, event->name);
232 else if (udev_device_get_devnode(dev) != NULL)
fbd0b64f
LP
233 l = strpcpy(&s, l,
234 udev_device_get_devnode(dev) + STRLEN("/dev/"));
0d53705b
DS
235 else
236 l = strpcpy(&s, l, udev_device_get_sysname(dev));
237 break;
238 case SUBST_LINKS: {
239 struct udev_list_entry *list_entry;
240
241 list_entry = udev_device_get_devlinks_list_entry(dev);
242 if (list_entry == NULL)
243 break;
fbd0b64f
LP
244 l = strpcpy(&s, l,
245 udev_list_entry_get_name(list_entry) + STRLEN("/dev/"));
0d53705b 246 udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry))
fbd0b64f
LP
247 l = strpcpyl(&s, l, " ",
248 udev_list_entry_get_name(list_entry) + STRLEN("/dev/"),
249 NULL);
0d53705b
DS
250 break;
251 }
252 case SUBST_ROOT:
253 l = strpcpy(&s, l, "/dev");
254 break;
255 case SUBST_SYS:
256 l = strpcpy(&s, l, "/sys");
257 break;
258 case SUBST_ENV:
259 if (attr == NULL) {
260 break;
261 } else {
262 const char *value;
263
264 value = udev_device_get_property_value(event->dev, attr);
265 if (value == NULL)
266 break;
267 l = strpcpy(&s, l, value);
268 break;
269 }
270 default:
271 log_error("unknown substitution type=%i", type);
272 break;
273 }
274
be452683 275 return s - dest;
0d53705b
DS
276}
277
e20a9171
DS
278size_t udev_event_apply_format(struct udev_event *event,
279 const char *src, char *dest, size_t size,
280 bool replace_whitespace) {
912541b0 281 struct udev_device *dev = event->dev;
912541b0 282 static const struct subst_map {
04a9d3a0
KS
283 const char *name;
284 const char fmt;
912541b0
KS
285 enum subst_type type;
286 } map[] = {
3fd0c4c6
KS
287 { .name = "devnode", .fmt = 'N', .type = SUBST_DEVNODE },
288 { .name = "tempnode", .fmt = 'N', .type = SUBST_DEVNODE },
289 { .name = "attr", .fmt = 's', .type = SUBST_ATTR },
290 { .name = "sysfs", .fmt = 's', .type = SUBST_ATTR },
291 { .name = "env", .fmt = 'E', .type = SUBST_ENV },
292 { .name = "kernel", .fmt = 'k', .type = SUBST_KERNEL },
293 { .name = "number", .fmt = 'n', .type = SUBST_KERNEL_NUMBER },
294 { .name = "driver", .fmt = 'd', .type = SUBST_DRIVER },
295 { .name = "devpath", .fmt = 'p', .type = SUBST_DEVPATH },
296 { .name = "id", .fmt = 'b', .type = SUBST_ID },
297 { .name = "major", .fmt = 'M', .type = SUBST_MAJOR },
298 { .name = "minor", .fmt = 'm', .type = SUBST_MINOR },
299 { .name = "result", .fmt = 'c', .type = SUBST_RESULT },
300 { .name = "parent", .fmt = 'P', .type = SUBST_PARENT },
301 { .name = "name", .fmt = 'D', .type = SUBST_NAME },
302 { .name = "links", .fmt = 'L', .type = SUBST_LINKS },
303 { .name = "root", .fmt = 'r', .type = SUBST_ROOT },
304 { .name = "sys", .fmt = 'S', .type = SUBST_SYS },
912541b0
KS
305 };
306 const char *from;
307 char *s;
308 size_t l;
309
3b64e4d4
TG
310 assert(dev);
311
912541b0
KS
312 from = src;
313 s = dest;
314 l = size;
315
316 for (;;) {
317 enum subst_type type = SUBST_UNKNOWN;
be452683
DS
318 char attrbuf[UTIL_PATH_SIZE];
319 char *attr = NULL;
320 size_t subst_len;
912541b0
KS
321
322 while (from[0] != '\0') {
323 if (from[0] == '$') {
324 /* substitute named variable */
14cb109d 325 unsigned i;
912541b0
KS
326
327 if (from[1] == '$') {
328 from++;
329 goto copy;
330 }
331
8fef0ff2 332 for (i = 0; i < ELEMENTSOF(map); i++) {
33502ffe 333 if (startswith(&from[1], map[i].name)) {
912541b0
KS
334 type = map[i].type;
335 from += strlen(map[i].name)+1;
912541b0
KS
336 goto subst;
337 }
338 }
339 } else if (from[0] == '%') {
340 /* substitute format char */
14cb109d 341 unsigned i;
912541b0
KS
342
343 if (from[1] == '%') {
344 from++;
345 goto copy;
346 }
347
8fef0ff2 348 for (i = 0; i < ELEMENTSOF(map); i++) {
912541b0
KS
349 if (from[1] == map[i].fmt) {
350 type = map[i].type;
351 from += 2;
912541b0
KS
352 goto subst;
353 }
354 }
355 }
065db052 356copy:
912541b0 357 /* copy char */
79a695f2 358 if (l < 2) /* need space for this char and the terminating NUL */
912541b0
KS
359 goto out;
360 s[0] = from[0];
361 from++;
362 s++;
363 l--;
364 }
365
366 goto out;
065db052 367subst:
912541b0
KS
368 /* extract possible $format{attr} */
369 if (from[0] == '{') {
14cb109d 370 unsigned i;
912541b0
KS
371
372 from++;
79a695f2 373 for (i = 0; from[i] != '}'; i++)
912541b0 374 if (from[i] == '\0') {
9f6445e3 375 log_error("missing closing brace for format '%s'", src);
912541b0
KS
376 goto out;
377 }
79a695f2 378
912541b0
KS
379 if (i >= sizeof(attrbuf))
380 goto out;
381 memcpy(attrbuf, from, i);
382 attrbuf[i] = '\0';
383 from += i+1;
384 attr = attrbuf;
385 } else {
386 attr = NULL;
387 }
388
be452683 389 subst_len = subst_format_var(event, dev, type, attr, s, l);
e20a9171 390
be452683
DS
391 /* SUBST_RESULT handles spaces itself */
392 if (replace_whitespace && type != SUBST_RESULT)
393 /* util_replace_whitespace can replace in-place,
394 * and does nothing if subst_len == 0
395 */
396 subst_len = util_replace_whitespace(s, s, subst_len);
e20a9171 397
be452683
DS
398 s += subst_len;
399 l -= subst_len;
912541b0 400 }
065db052
KS
401
402out:
79a695f2 403 assert(l >= 1);
912541b0 404 s[0] = '\0';
912541b0 405 return l;
f1128767
KS
406}
407
2181d30a 408static int spawn_exec(struct udev_event *event,
8314de1d 409 const char *cmd, char *const argv[], char **envp,
9ec6e95b 410 int fd_stdout, int fd_stderr) {
19c784c4 411 _cleanup_close_ int fd = -1;
f6e0a353 412 int r;
912541b0
KS
413
414 /* discard child output or connect to pipe */
415 fd = open("/dev/null", O_RDWR);
416 if (fd >= 0) {
f6e0a353
TG
417 r = dup2(fd, STDIN_FILENO);
418 if (r < 0)
419 log_warning_errno(errno, "redirecting stdin failed: %m");
420
421 if (fd_stdout < 0) {
422 r = dup2(fd, STDOUT_FILENO);
423 if (r < 0)
424 log_warning_errno(errno, "redirecting stdout failed: %m");
425 }
426
427 if (fd_stderr < 0) {
428 r = dup2(fd, STDERR_FILENO);
429 if (r < 0)
430 log_warning_errno(errno, "redirecting stderr failed: %m");
431 }
19c784c4 432 } else
f6e0a353 433 log_warning_errno(errno, "open /dev/null failed: %m");
912541b0
KS
434
435 /* connect pipes to std{out,err} */
436 if (fd_stdout >= 0) {
f6e0a353
TG
437 r = dup2(fd_stdout, STDOUT_FILENO);
438 if (r < 0)
439 log_warning_errno(errno, "redirecting stdout failed: %m");
440
441 fd_stdout = safe_close(fd_stdout);
912541b0 442 }
f6e0a353 443
912541b0 444 if (fd_stderr >= 0) {
f6e0a353
TG
445 r = dup2(fd_stderr, STDERR_FILENO);
446 if (r < 0)
447 log_warning_errno(errno, "redirecting stdout failed: %m");
448
449 fd_stderr = safe_close(fd_stderr);
912541b0
KS
450 }
451
912541b0
KS
452 execve(argv[0], argv, envp);
453
454 /* exec failed */
e1427b13 455 return log_error_errno(errno, "failed to execute '%s' '%s': %m", argv[0], cmd);
2181d30a
KS
456}
457
f18f225c 458static void spawn_read(struct udev_event *event,
dd5eddd2
KS
459 usec_t timeout_usec,
460 const char *cmd,
461 int fd_stdout, int fd_stderr,
9ec6e95b 462 char *result, size_t ressize) {
4cd5d5ad
TG
463 _cleanup_close_ int fd_ep = -1;
464 struct epoll_event ep_outpipe = {
465 .events = EPOLLIN,
466 .data.ptr = &fd_stdout,
467 };
468 struct epoll_event ep_errpipe = {
469 .events = EPOLLIN,
470 .data.ptr = &fd_stderr,
471 };
912541b0 472 size_t respos = 0;
4cd5d5ad 473 int r;
912541b0
KS
474
475 /* read from child if requested */
476 if (fd_stdout < 0 && fd_stderr < 0)
477 return;
478
479 fd_ep = epoll_create1(EPOLL_CLOEXEC);
480 if (fd_ep < 0) {
56f64d95 481 log_error_errno(errno, "error creating epoll fd: %m");
4cd5d5ad 482 return;
912541b0
KS
483 }
484
485 if (fd_stdout >= 0) {
4cd5d5ad
TG
486 r = epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_stdout, &ep_outpipe);
487 if (r < 0) {
56f64d95 488 log_error_errno(errno, "fail to add stdout fd to epoll: %m");
4cd5d5ad 489 return;
912541b0
KS
490 }
491 }
492
493 if (fd_stderr >= 0) {
4cd5d5ad
TG
494 r = epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_stderr, &ep_errpipe);
495 if (r < 0) {
56f64d95 496 log_error_errno(errno, "fail to add stderr fd to epoll: %m");
4cd5d5ad 497 return;
912541b0
KS
498 }
499 }
500
501 /* read child output */
502 while (fd_stdout >= 0 || fd_stderr >= 0) {
503 int timeout;
504 int fdcount;
505 struct epoll_event ev[4];
506 int i;
507
dd5eddd2 508 if (timeout_usec > 0) {
40fe8b11 509 usec_t age_usec;
912541b0 510
3285baa8 511 age_usec = now(CLOCK_MONOTONIC) - event->birth_usec;
dd5eddd2 512 if (age_usec >= timeout_usec) {
9f6445e3 513 log_error("timeout '%s'", cmd);
4cd5d5ad 514 return;
912541b0 515 }
dd5eddd2 516 timeout = ((timeout_usec - age_usec) / USEC_PER_MSEC) + MSEC_PER_SEC;
912541b0
KS
517 } else {
518 timeout = -1;
519 }
520
8fef0ff2 521 fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev), timeout);
912541b0
KS
522 if (fdcount < 0) {
523 if (errno == EINTR)
524 continue;
56f64d95 525 log_error_errno(errno, "failed to poll: %m");
4cd5d5ad
TG
526 return;
527 } else if (fdcount == 0) {
9f6445e3 528 log_error("timeout '%s'", cmd);
4cd5d5ad 529 return;
912541b0
KS
530 }
531
532 for (i = 0; i < fdcount; i++) {
533 int *fd = (int *)ev[i].data.ptr;
534
3f796750
TG
535 if (*fd < 0)
536 continue;
537
912541b0
KS
538 if (ev[i].events & EPOLLIN) {
539 ssize_t count;
540 char buf[4096];
541
542 count = read(*fd, buf, sizeof(buf)-1);
543 if (count <= 0)
544 continue;
545 buf[count] = '\0';
546
547 /* store stdout result */
548 if (result != NULL && *fd == fd_stdout) {
549 if (respos + count < ressize) {
550 memcpy(&result[respos], buf, count);
551 respos += count;
552 } else {
1fa2f38f 553 log_error("'%s' ressize %zu too short", cmd, ressize);
912541b0
KS
554 }
555 }
556
557 /* log debug output only if we watch stderr */
558 if (fd_stderr >= 0) {
559 char *pos;
560 char *line;
561
562 pos = buf;
563 while ((line = strsep(&pos, "\n"))) {
564 if (pos != NULL || line[0] != '\0')
9f6445e3 565 log_debug("'%s'(%s) '%s'", cmd, *fd == fd_stdout ? "out" : "err" , line);
912541b0
KS
566 }
567 }
568 } else if (ev[i].events & EPOLLHUP) {
4cd5d5ad
TG
569 r = epoll_ctl(fd_ep, EPOLL_CTL_DEL, *fd, NULL);
570 if (r < 0) {
56f64d95 571 log_error_errno(errno, "failed to remove fd from epoll: %m");
4cd5d5ad 572 return;
912541b0
KS
573 }
574 *fd = -1;
575 }
576 }
577 }
578
579 /* return the child's stdout string */
baa30fbc 580 if (result != NULL)
912541b0 581 result[respos] = '\0';
2181d30a
KS
582}
583
8128f229
TG
584static int on_spawn_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
585 Spawn *spawn = userdata;
586 char timeout[FORMAT_TIMESTAMP_RELATIVE_MAX];
912541b0 587
8128f229 588 assert(spawn);
912541b0 589
8128f229 590 kill_and_sigcont(spawn->pid, SIGKILL);
912541b0 591
8128f229
TG
592 log_error("spawned process '%s' ["PID_FMT"] timed out after %s, killing", spawn->cmd, spawn->pid,
593 format_timestamp_relative(timeout, sizeof(timeout), spawn->timeout));
912541b0 594
8128f229
TG
595 return 1;
596}
67117413 597
8128f229
TG
598static int on_spawn_timeout_warning(sd_event_source *s, uint64_t usec, void *userdata) {
599 Spawn *spawn = userdata;
600 char timeout[FORMAT_TIMESTAMP_RELATIVE_MAX];
912541b0 601
8128f229 602 assert(spawn);
67117413 603
8128f229
TG
604 log_warning("spawned process '%s' ["PID_FMT"] is taking longer than %s to complete", spawn->cmd, spawn->pid,
605 format_timestamp_relative(timeout, sizeof(timeout), spawn->timeout));
606
607 return 1;
608}
609
610static int on_spawn_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata) {
611 Spawn *spawn = userdata;
612
613 assert(spawn);
614
615 switch (si->si_code) {
616 case CLD_EXITED:
53318514
TG
617 if (si->si_status == 0) {
618 log_debug("Process '%s' succeeded.", spawn->cmd);
8128f229
TG
619 sd_event_exit(sd_event_source_get_event(s), 0);
620
621 return 1;
53318514
TG
622 } else if (spawn->accept_failure)
623 log_debug("Process '%s' failed with exit code %i.", spawn->cmd, si->si_status);
624 else
625 log_warning("Process '%s' failed with exit code %i.", spawn->cmd, si->si_status);
912541b0 626
8128f229
TG
627 break;
628 case CLD_KILLED:
629 case CLD_DUMPED:
53318514 630 log_warning("Process '%s' terminated by signal %s.", spawn->cmd, signal_to_string(si->si_status));
912541b0 631
8128f229
TG
632 break;
633 default:
53318514 634 log_error("Process '%s' failed due to unknown reason.", spawn->cmd);
8128f229 635 }
912541b0 636
8128f229
TG
637 sd_event_exit(sd_event_source_get_event(s), -EIO);
638
639 return 1;
640}
641
642static int spawn_wait(struct udev_event *event,
643 usec_t timeout_usec,
644 usec_t timeout_warn_usec,
53318514
TG
645 const char *cmd, pid_t pid,
646 bool accept_failure) {
8128f229
TG
647 Spawn spawn = {
648 .cmd = cmd,
649 .pid = pid,
53318514 650 .accept_failure = accept_failure,
8128f229 651 };
4afd3348 652 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
8128f229
TG
653 int r, ret;
654
655 r = sd_event_new(&e);
656 if (r < 0)
657 return r;
658
659 if (timeout_usec > 0) {
660 usec_t usec, age_usec;
661
3285baa8 662 usec = now(CLOCK_MONOTONIC);
8128f229
TG
663 age_usec = usec - event->birth_usec;
664 if (age_usec < timeout_usec) {
665 if (timeout_warn_usec > 0 && timeout_warn_usec < timeout_usec && age_usec < timeout_warn_usec) {
666 spawn.timeout_warn = timeout_warn_usec - age_usec;
667
3285baa8 668 r = sd_event_add_time(e, NULL, CLOCK_MONOTONIC,
920b52e4
TA
669 usec + spawn.timeout_warn, USEC_PER_SEC,
670 on_spawn_timeout_warning, &spawn);
8128f229
TG
671 if (r < 0)
672 return r;
912541b0 673 }
8128f229
TG
674
675 spawn.timeout = timeout_usec - age_usec;
676
3285baa8 677 r = sd_event_add_time(e, NULL, CLOCK_MONOTONIC,
8128f229
TG
678 usec + spawn.timeout, USEC_PER_SEC, on_spawn_timeout, &spawn);
679 if (r < 0)
680 return r;
912541b0
KS
681 }
682 }
8128f229
TG
683
684 r = sd_event_add_child(e, NULL, pid, WEXITED, on_spawn_sigchld, &spawn);
685 if (r < 0)
686 return r;
687
688 r = sd_event_loop(e);
689 if (r < 0)
690 return r;
691
692 r = sd_event_get_exit_code(e, &ret);
693 if (r < 0)
694 return r;
695
696 return ret;
2181d30a
KS
697}
698
699int udev_event_spawn(struct udev_event *event,
dd5eddd2 700 usec_t timeout_usec,
67117413 701 usec_t timeout_warn_usec,
53318514 702 bool accept_failure,
bbf35206 703 const char *cmd,
dd5eddd2 704 char *result, size_t ressize) {
feaa6db7
YW
705 _cleanup_close_pair_ int outpipe[2] = {-1, -1}, errpipe[2] = {-1, -1};
706 _cleanup_strv_free_ char **argv = NULL;
912541b0 707 pid_t pid;
feaa6db7 708 int r;
912541b0 709
912541b0 710 /* pipes from child to parent */
feaa6db7
YW
711 if (!result || log_get_max_level() >= LOG_INFO)
712 if (pipe2(outpipe, O_NONBLOCK) != 0)
713 return log_error_errno(errno, "Failed to create pipe for command '%s': %m", cmd);
912541b0 714
feaa6db7
YW
715 if (log_get_max_level() >= LOG_INFO)
716 if (pipe2(errpipe, O_NONBLOCK) != 0)
717 return log_error_errno(errno, "Failed to create pipe for command '%s': %m", cmd);
718
719 argv = strv_split_full(cmd, NULL, SPLIT_QUOTES|SPLIT_RELAX);
720 if (!argv)
721 return log_oom();
722
723 /* allow programs in /usr/lib/udev/ to be called without the path */
724 if (!path_is_absolute(argv[0])) {
725 char *program;
726
727 program = path_join(NULL, UDEVLIBEXECDIR, argv[0]);
728 if (!program)
729 return log_oom();
bbf35206 730
feaa6db7
YW
731 free_and_replace(argv[0], program);
732 }
733
3ad4d482
YW
734 log_debug("Starting '%s'", cmd);
735
6ce075a2 736 r = safe_fork("(spawn)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
feaa6db7
YW
737 if (r < 0)
738 return log_error_errno(r, "Failed to fork() to execute command '%s': %m", cmd);
739 if (r == 0) {
912541b0 740 /* child closes parent's ends of pipes */
7f6e12b0
LP
741 outpipe[READ_END] = safe_close(outpipe[READ_END]);
742 errpipe[READ_END] = safe_close(errpipe[READ_END]);
912541b0 743
bbf35206 744 spawn_exec(event, cmd, argv, udev_device_get_properties_envp(event->dev),
b49d9b50 745 outpipe[WRITE_END], errpipe[WRITE_END]);
912541b0 746
bbf35206
TG
747 _exit(2);
748 }
912541b0 749
4c253ed1
LP
750 /* parent closed child's ends of pipes */
751 outpipe[WRITE_END] = safe_close(outpipe[WRITE_END]);
752 errpipe[WRITE_END] = safe_close(errpipe[WRITE_END]);
912541b0 753
4c253ed1
LP
754 spawn_read(event,
755 timeout_usec,
756 cmd,
757 outpipe[READ_END], errpipe[READ_END],
758 result, ressize);
759
feaa6db7
YW
760 r = spawn_wait(event, timeout_usec, timeout_warn_usec, cmd, pid, accept_failure);
761 if (r < 0)
762 return log_error_errno(r, "Failed to wait spawned command '%s': %m", cmd);
2181d30a 763
feaa6db7 764 return r;
2181d30a
KS
765}
766
9ec6e95b 767static int rename_netif(struct udev_event *event) {
912541b0 768 struct udev_device *dev = event->dev;
16d26d55
TG
769 char name[IFNAMSIZ];
770 const char *oldname;
771 int r;
772
773 oldname = udev_device_get_sysname(dev);
912541b0 774
16d26d55 775 strscpy(name, IFNAMSIZ, event->name);
912541b0 776
4c83d994 777 r = rtnl_set_link_name(&event->rtnl, udev_device_get_ifindex(dev), name);
f647962d
MS
778 if (r < 0)
779 return log_error_errno(r, "Error changing net interface name '%s' to '%s': %m", oldname, name);
16d26d55 780
ff49bc32 781 log_debug("renamed network interface '%s' to '%s'", oldname, name);
16d26d55 782
4c83d994 783 return 0;
d46f37fd
KS
784}
785
dd5eddd2 786void udev_event_execute_rules(struct udev_event *event,
adeba500 787 usec_t timeout_usec, usec_t timeout_warn_usec,
9b5150b6 788 Hashmap *properties_list,
8314de1d 789 struct udev_rules *rules) {
912541b0 790 struct udev_device *dev = event->dev;
912541b0
KS
791
792 if (udev_device_get_subsystem(dev) == NULL)
1ea97217 793 return;
912541b0 794
090be865 795 if (streq(udev_device_get_action(dev), "remove")) {
107f2e25
TG
796 udev_device_read_db(dev);
797 udev_device_tag_index(dev, NULL, false);
798 udev_device_delete_db(dev);
799
912541b0 800 if (major(udev_device_get_devnum(dev)) != 0)
70068602 801 udev_watch_end(dev->device);
912541b0 802
adeba500
KS
803 udev_rules_apply_to_event(rules, event,
804 timeout_usec, timeout_warn_usec,
8314de1d 805 properties_list);
912541b0
KS
806
807 if (major(udev_device_get_devnum(dev)) != 0)
a2554ace 808 udev_node_remove(dev->device);
912541b0 809 } else {
8f0f13f0 810 event->dev_db = udev_device_clone_with_db(dev);
912541b0 811 if (event->dev_db != NULL) {
912541b0
KS
812 /* disable watch during event processing */
813 if (major(udev_device_get_devnum(dev)) != 0)
70068602 814 udev_watch_end(event->dev_db->device);
912541b0 815
9eba69df
ZJS
816 if (major(udev_device_get_devnum(dev)) == 0 &&
817 streq(udev_device_get_action(dev), "move"))
818 udev_device_copy_properties(dev, event->dev_db);
819 }
b081b27e 820
adeba500
KS
821 udev_rules_apply_to_event(rules, event,
822 timeout_usec, timeout_warn_usec,
8314de1d 823 properties_list);
912541b0
KS
824
825 /* rename a new network interface, if needed */
090be865
TA
826 if (udev_device_get_ifindex(dev) > 0 && streq(udev_device_get_action(dev), "add") &&
827 event->name != NULL && !streq(event->name, udev_device_get_sysname(dev))) {
1ea97217 828 int r;
912541b0 829
1ea97217 830 r = rename_netif(event);
243d1825
TG
831 if (r < 0)
832 log_warning_errno(r, "could not rename interface '%d' from '%s' to '%s': %m", udev_device_get_ifindex(dev),
833 udev_device_get_sysname(dev), event->name);
834 else {
243d1825
TG
835 r = udev_device_rename(dev, event->name);
836 if (r < 0)
837 log_warning_errno(r, "renamed interface '%d' from '%s' to '%s', but could not update udev_device: %m",
838 udev_device_get_ifindex(dev), udev_device_get_sysname(dev), event->name);
3738cc85 839 else
9f6445e3 840 log_debug("changed devpath to '%s'", udev_device_get_devpath(dev));
912541b0
KS
841 }
842 }
843
b0a00806 844 if (major(udev_device_get_devnum(dev)) > 0) {
9a8ae49d
KS
845 bool apply;
846
912541b0
KS
847 /* remove/update possible left-over symlinks from old database entry */
848 if (event->dev_db != NULL)
a2554ace 849 udev_node_update_old_links(dev->device, event->dev_db->device);
912541b0 850
1edefa4f
KS
851 if (!event->owner_set)
852 event->uid = udev_device_get_devnode_uid(dev);
853
854 if (!event->group_set)
855 event->gid = udev_device_get_devnode_gid(dev);
856
912541b0
KS
857 if (!event->mode_set) {
858 if (udev_device_get_devnode_mode(dev) > 0) {
859 /* kernel supplied value */
860 event->mode = udev_device_get_devnode_mode(dev);
861 } else if (event->gid > 0) {
862 /* default 0660 if a group is assigned */
863 event->mode = 0660;
864 } else {
865 /* default 0600 */
866 event->mode = 0600;
867 }
868 }
869
9a8ae49d 870 apply = streq(udev_device_get_action(dev), "add") || event->owner_set || event->group_set || event->mode_set;
d838e145 871 udev_node_add(dev->device, apply, event->mode, event->uid, event->gid, event->seclabel_list);
912541b0
KS
872 }
873
874 /* preserve old, or get new initialization timestamp */
1b14c3cf 875 udev_device_ensure_usec_initialized(event->dev, event->dev_db);
912541b0
KS
876
877 /* (re)write database file */
912541b0 878 udev_device_tag_index(dev, event->dev_db, true);
353f6058 879 udev_device_update_db(dev);
912541b0
KS
880 udev_device_set_is_initialized(dev);
881
353f6058 882 event->dev_db = udev_device_unref(event->dev_db);
912541b0 883 }
d46f37fd 884}
2d73813e 885
8314de1d 886void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec) {
29448498
YW
887 const char *cmd;
888 void *val;
889 Iterator i;
912541b0 890
29448498
YW
891 HASHMAP_FOREACH_KEY(val, cmd, event->run_list, i) {
892 enum udev_builtin_cmd builtin_cmd = PTR_TO_INT(val);
bbf35206 893 char command[UTIL_PATH_SIZE];
83cd6b75 894
e20a9171 895 udev_event_apply_format(event, cmd, command, sizeof(command), false);
912541b0 896
c45b369d 897 if (builtin_cmd >= 0 && builtin_cmd < _UDEV_BUILTIN_MAX)
3d6194e8 898 udev_builtin_run(event->dev->device, builtin_cmd, command, false);
bbf35206 899 else {
912541b0 900 if (event->exec_delay > 0) {
bbf35206 901 log_debug("delay execution of '%s'", command);
912541b0
KS
902 sleep(event->exec_delay);
903 }
904
bbf35206 905 udev_event_spawn(event, timeout_usec, timeout_warn_usec, false, command, NULL, 0);
912541b0
KS
906 }
907 }
2d73813e 908}