]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/udev/udev-event.c
udev: do not read UdevEvent object before checking it is non-NULL
[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;
2740750d
YW
699 int ifindex, r;
700
701 if (!event->name)
702 return 0; /* No new name is requested. */
703
704 r = sd_device_get_sysname(dev, &oldname);
705 if (r < 0)
706 return log_device_error_errno(dev, r, "Failed to get sysname: %m");
707
708 if (streq(event->name, oldname))
709 return 0; /* The interface name is already requested name. */
710
711 r = sd_device_get_property_value(dev, "ACTION", &action);
712 if (r < 0)
713 return log_device_error_errno(dev, r, "Failed to get property 'ACTION': %m");
714
715 if (!streq(action, "add"))
716 return 0; /* Rename the interface only when it is added. */
16d26d55 717
2740750d
YW
718 r = sd_device_get_ifindex(dev, &ifindex);
719 if (r == -ENOENT)
720 return 0; /* Device is not a network interface. */
721 if (r < 0)
722 return log_device_error_errno(dev, r, "Failed to get ifindex: %m");
912541b0 723
589384be 724 r = rtnl_set_link_name(&event->rtnl, ifindex, event->name);
2740750d 725 if (r < 0)
589384be
YW
726 return log_device_error_errno(dev, r, "Failed to rename network interface %i from '%s' to '%s': %m",
727 ifindex, oldname, event->name);
912541b0 728
2740750d 729 r = device_rename(dev, event->name);
f647962d 730 if (r < 0)
589384be
YW
731 return log_device_warning_errno(dev, r, "Network interface %i is renamed from '%s' to '%s', "
732 "but could not update sd_device object: %m",
733 ifindex, oldname, event->name);
16d26d55 734
589384be 735 log_device_debug(dev, "Network interface %i is renamed from '%s' to '%s'", ifindex, oldname, event->name);
16d26d55 736
2740750d 737 return 1;
d46f37fd
KS
738}
739
2e088715 740static int update_devnode(UdevEvent *event) {
cf28ad46 741 sd_device *dev = event->dev;
e52eaf56 742 const char *action;
e52eaf56
YW
743 bool apply;
744 int r;
745
7af1c780 746 r = sd_device_get_devnum(dev, NULL);
e52eaf56
YW
747 if (r == -ENOENT)
748 return 0;
749 if (r < 0)
750 return log_device_error_errno(dev, r, "Failed to get devnum: %m");
751
752 /* remove/update possible left-over symlinks from old database entry */
480ecb7d
YW
753 if (event->dev_db_clone)
754 (void) udev_node_update_old_links(dev, event->dev_db_clone);
e52eaf56
YW
755
756 if (!event->owner_set) {
757 r = device_get_devnode_uid(dev, &event->uid);
758 if (r < 0 && r != -ENOENT)
759 return log_device_error_errno(dev, r, "Failed to get devnode UID: %m");
760 }
761
762 if (!event->group_set) {
763 r = device_get_devnode_gid(dev, &event->gid);
764 if (r < 0 && r != -ENOENT)
765 return log_device_error_errno(dev, r, "Failed to get devnode GID: %m");
766 }
767
768 if (!event->mode_set) {
769 r = device_get_devnode_mode(dev, &event->mode);
770 if (r < 0 && r != -ENOENT)
771 return log_device_error_errno(dev, r, "Failed to get devnode mode: %m");
772 if (r == -ENOENT) {
773 if (event->gid > 0)
774 /* default 0660 if a group is assigned */
775 event->mode = 0660;
776 else
777 /* default 0600 */
778 event->mode = 0600;
779 }
780 }
781
782 r = sd_device_get_property_value(dev, "ACTION", &action);
783 if (r < 0)
784 return log_device_error_errno(dev, r, "Failed to get property 'ACTION': %m");
785
786 apply = streq(action, "add") || event->owner_set || event->group_set || event->mode_set;
787 return udev_node_add(dev, apply, event->mode, event->uid, event->gid, event->seclabel_list);
788}
789
eb1f9e30 790static void event_execute_rules_on_remove(
2e088715 791 UdevEvent *event,
66f737b4 792 usec_t timeout_usec,
eb1f9e30 793 Hashmap *properties_list,
9a07157d 794 UdevRules *rules) {
912541b0 795
cf28ad46 796 sd_device *dev = event->dev;
eb1f9e30 797 int r;
912541b0 798
ebcc52fa 799 r = device_read_db_internal(dev, true);
eb1f9e30
YW
800 if (r < 0)
801 log_device_debug_errno(dev, r, "Failed to read database under /run/udev/data/: %m");
107f2e25 802
eb1f9e30
YW
803 r = device_tag_index(dev, NULL, false);
804 if (r < 0)
805 log_device_debug_errno(dev, r, "Failed to remove corresponding tag files under /run/udev/tag/, ignoring: %m");
912541b0 806
eb1f9e30
YW
807 r = device_delete_db(dev);
808 if (r < 0)
809 log_device_debug_errno(dev, r, "Failed to delete database under /run/udev/data/, ignoring: %m");
912541b0 810
d4a95a95 811 if (sd_device_get_devnum(dev, NULL) >= 0)
eb1f9e30
YW
812 (void) udev_watch_end(dev);
813
66f737b4 814 (void) udev_rules_apply_to_event(rules, event, timeout_usec, properties_list);
eb1f9e30 815
d4a95a95 816 if (sd_device_get_devnum(dev, NULL) >= 0)
eb1f9e30
YW
817 (void) udev_node_remove(dev);
818}
819
2e088715 820int udev_event_execute_rules(UdevEvent *event,
66f737b4 821 usec_t timeout_usec,
eb1f9e30 822 Hashmap *properties_list,
9a07157d 823 UdevRules *rules) {
eb1f9e30 824 const char *subsystem, *action;
6d0fdf45 825 sd_device *dev;
eb1f9e30
YW
826 int r;
827
828 assert(event);
829 assert(rules);
830
6d0fdf45
YW
831 dev = event->dev;
832
eb1f9e30
YW
833 r = sd_device_get_subsystem(dev, &subsystem);
834 if (r < 0)
835 return log_device_error_errno(dev, r, "Failed to get subsystem: %m");
836
837 r = sd_device_get_property_value(dev, "ACTION", &action);
838 if (r < 0)
839 return log_device_error_errno(dev, r, "Failed to get property 'ACTION': %m");
b081b27e 840
eb1f9e30 841 if (streq(action, "remove")) {
66f737b4 842 event_execute_rules_on_remove(event, timeout_usec, properties_list, rules);
eb1f9e30
YW
843 return 0;
844 }
912541b0 845
480ecb7d 846 r = device_clone_with_db(dev, &event->dev_db_clone);
eb1f9e30
YW
847 if (r < 0)
848 log_device_debug_errno(dev, r, "Failed to clone sd_device object, ignoring: %m");
912541b0 849
480ecb7d 850 if (event->dev_db_clone) {
7af1c780 851 r = sd_device_get_devnum(dev, NULL);
eb1f9e30
YW
852 if (r < 0) {
853 if (r != -ENOENT)
854 log_device_debug_errno(dev, r, "Failed to get devnum, ignoring: %m");
912541b0 855
eb1f9e30 856 if (streq(action, "move")) {
480ecb7d 857 r = device_copy_properties(dev, event->dev_db_clone);
eb1f9e30
YW
858 if (r < 0)
859 log_device_debug_errno(dev, r, "Failed to copy properties from cloned device, ignoring: %m");
860 }
861 } else
862 /* Disable watch during event processing. */
480ecb7d 863 (void) udev_watch_end(event->dev_db_clone);
912541b0 864 }
eb1f9e30 865
66f737b4 866 (void) udev_rules_apply_to_event(rules, event, timeout_usec, properties_list);
eb1f9e30
YW
867
868 (void) rename_netif(event);
869 (void) update_devnode(event);
870
871 /* preserve old, or get new initialization timestamp */
480ecb7d 872 r = device_ensure_usec_initialized(dev, event->dev_db_clone);
eb1f9e30
YW
873 if (r < 0)
874 log_device_debug_errno(dev, r, "Failed to set initialization timestamp, ignoring: %m");
875
876 /* (re)write database file */
480ecb7d 877 r = device_tag_index(dev, event->dev_db_clone, true);
eb1f9e30
YW
878 if (r < 0)
879 log_device_debug_errno(dev, r, "Failed to update tags under /run/udev/tag/, ignoring: %m");
880
881 r = device_update_db(dev);
882 if (r < 0)
883 log_device_debug_errno(dev, r, "Failed to update database under /run/udev/data/, ignoring: %m");
884
885 device_set_is_initialized(dev);
886
480ecb7d 887 event->dev_db_clone = sd_device_unref(event->dev_db_clone);
eb1f9e30
YW
888
889 return 0;
d46f37fd 890}
2d73813e 891
2e088715 892void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec) {
29448498
YW
893 const char *cmd;
894 void *val;
895 Iterator i;
912541b0 896
29448498
YW
897 HASHMAP_FOREACH_KEY(val, cmd, event->run_list, i) {
898 enum udev_builtin_cmd builtin_cmd = PTR_TO_INT(val);
bbf35206 899 char command[UTIL_PATH_SIZE];
83cd6b75 900
e20a9171 901 udev_event_apply_format(event, cmd, command, sizeof(command), false);
912541b0 902
c45b369d 903 if (builtin_cmd >= 0 && builtin_cmd < _UDEV_BUILTIN_MAX)
cf28ad46 904 udev_builtin_run(event->dev, builtin_cmd, command, false);
bbf35206 905 else {
6b92f429 906 if (event->exec_delay_usec > 0) {
bbf35206 907 log_debug("delay execution of '%s'", command);
6b92f429 908 (void) usleep(event->exec_delay_usec);
912541b0
KS
909 }
910
a7521142 911 (void) udev_event_spawn(event, timeout_usec, false, command, NULL, 0);
912541b0
KS
912 }
913 }
2d73813e 914}