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