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