1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 #include <errno.h>
4 #include <getopt.h>
5
6 #include "sd-device.h"
7 #include "sd-event.h"
8
9 #include "device-enumerator-private.h"
10 #include "device-private.h"
11 #include "device-util.h"
12 #include "fd-util.h"
13 #include "fileio.h"
14 #include "parse-util.h"
15 #include "path-util.h"
16 #include "process-util.h"
17 #include "set.h"
18 #include "string-util.h"
19 #include "strv.h"
20 #include "udevadm.h"
21 #include "udevadm-util.h"
22 #include "udev-ctrl.h"
23 #include "virt.h"
24
25 static bool arg_verbose = false;
26 static bool arg_dry_run = false;
27 static bool arg_quiet = false;
28 static bool arg_uuid = false;
29
exec_list(sd_device_enumerator * e,sd_device_action_t action,Hashmap * settle_hashmap)30 static int exec_list(
31 sd_device_enumerator *e,
32 sd_device_action_t action,
33 Hashmap *settle_hashmap) {
34
35 bool skip_uuid_logic = false;
36 const char *action_str;
37 sd_device *d;
38 int r, ret = 0;
39
40 action_str = device_action_to_string(action);
41
42 FOREACH_DEVICE_AND_SUBSYSTEM(e, d) {
43 sd_id128_t id = SD_ID128_NULL;
44 const char *syspath;
45
46 r = sd_device_get_syspath(d, &syspath);
47 if (r < 0) {
48 log_debug_errno(r, "Failed to get syspath of enumerated devices, ignoring: %m");
49 continue;
50 }
51
52 if (arg_verbose)
53 printf("%s\n", syspath);
54
55 if (arg_dry_run)
56 continue;
57
58 /* Use the UUID mode if the user explicitly asked for it, or if --settle has been specified,
59 * so that we can recognize our own uevent. */
60 r = sd_device_trigger_with_uuid(d, action, (arg_uuid || settle_hashmap) && !skip_uuid_logic ? &id : NULL);
61 if (r == -EINVAL && !arg_uuid && settle_hashmap && !skip_uuid_logic) {
62 /* If we specified a UUID because of the settling logic, and we got EINVAL this might
63 * be caused by an old kernel which doesn't know the UUID logic (pre-4.13). Let's try
64 * if it works without the UUID logic then. */
65 r = sd_device_trigger(d, action);
66 if (r != -EINVAL)
67 skip_uuid_logic = true; /* dropping the uuid stuff changed the return code,
68 * hence don't bother next time */
69 }
70 if (r < 0) {
71 /* ENOENT may be returned when a device does not have /uevent or is already
72 * removed. Hence, this is logged at debug level and ignored.
73 *
74 * ENODEV may be returned by some buggy device drivers e.g. /sys/devices/vio.
75 * See,
76 * https://github.com/systemd/systemd/issues/13652#issuecomment-535129791 and
77 * https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1845319.
78 * So, this error is ignored, but logged at warning level to encourage people to
79 * fix the driver.
80 *
81 * EROFS is returned when /sys is read only. In that case, all subsequent
82 * writes will also fail, hence return immediately.
83 *
84 * EACCES or EPERM may be returned when this is invoked by non-priviledged user.
85 * We do NOT return immediately, but continue operation and propagate the error.
86 * Why? Some device can be owned by a user, e.g., network devices configured in
87 * a network namespace. See, https://github.com/systemd/systemd/pull/18559 and
88 * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ebb4a4bf76f164457184a3f43ebc1552416bc823
89 *
90 * All other errors are logged at error level, but let's continue the operation,
91 * and propagate the error.
92 */
93
94 bool ignore = IN_SET(r, -ENOENT, -ENODEV);
95 int level =
96 arg_quiet ? LOG_DEBUG :
97 r == -ENOENT ? LOG_DEBUG :
98 r == -ENODEV ? LOG_WARNING : LOG_ERR;
99
100 log_device_full_errno(d, level, r,
101 "Failed to write '%s' to '%s/uevent'%s: %m",
102 action_str, syspath, ignore ? ", ignoring" : "");
103
104 if (r == -EROFS)
105 return r;
106 if (ret == 0 && !ignore)
107 ret = r;
108 continue;
109 }
110
111 /* If the user asked for it, write event UUID to stdout */
112 if (arg_uuid)
113 printf(SD_ID128_UUID_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(id));
114
115 if (settle_hashmap) {
116 _cleanup_free_ sd_id128_t *mid = NULL;
117 _cleanup_free_ char *sp = NULL;
118
119 sp = strdup(syspath);
120 if (!sp)
121 return log_oom();
122
123 mid = newdup(sd_id128_t, &id, 1);
124 if (!d)
125 return log_oom();
126
127 r = hashmap_put(settle_hashmap, sp, mid);
128 if (r < 0)
129 return log_oom();
130
131 TAKE_PTR(sp);
132 TAKE_PTR(mid);
133 }
134 }
135
136 return ret;
137 }
138
device_monitor_handler(sd_device_monitor * m,sd_device * dev,void * userdata)139 static int device_monitor_handler(sd_device_monitor *m, sd_device *dev, void *userdata) {
140 Hashmap *settle_hashmap = userdata;
141 sd_id128_t *settle_id;
142 const char *syspath;
143 char *k;
144 int r;
145
146 assert(dev);
147 assert(settle_hashmap);
148
149 r = sd_device_get_syspath(dev, &syspath);
150 if (r < 0) {
151 log_debug_errno(r, "Failed to get syspath of device event, ignoring: %m");
152 return 0;
153 }
154
155 settle_id = hashmap_get2(settle_hashmap, syspath, (void**) &k);
156 if (!settle_id) {
157 log_debug("Got uevent for unexpected device '%s', ignoring.", syspath);
158 return 0;
159 }
160 if (!sd_id128_is_null(*settle_id)) { /* If this is SD_ID128_NULL then we are on pre-4.13 and have no UUID to check, hence don't */
161 sd_id128_t event_id;
162
163 r = sd_device_get_trigger_uuid(dev, &event_id);
164 if (r < 0) {
165 log_debug_errno(r, "Got uevent without synthetic UUID for device '%s', ignoring: %m", syspath);
166 return 0;
167 }
168
169 if (!sd_id128_equal(event_id, *settle_id)) {
170 log_debug("Got uevent not matching expected UUID for device '%s', ignoring.", syspath);
171 return 0;
172 }
173 }
174
175 if (arg_verbose)
176 printf("settle %s\n", syspath);
177
178 if (arg_uuid)
179 printf("settle " SD_ID128_UUID_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(*settle_id));
180
181 free(hashmap_remove(settle_hashmap, syspath));
182 free(k);
183
184 if (hashmap_isempty(settle_hashmap))
185 return sd_event_exit(sd_device_monitor_get_event(m), 0);
186
187 return 0;
188 }
189
keyval(const char * str,const char ** key,const char ** val)190 static char* keyval(const char *str, const char **key, const char **val) {
191 char *buf, *pos;
192
193 buf = strdup(str);
194 if (!buf)
195 return NULL;
196
197 pos = strchr(buf, '=');
198 if (pos) {
199 pos[0] = 0;
200 pos++;
201 }
202
203 *key = buf;
204 *val = pos;
205
206 return buf;
207 }
208
help(void)209 static int help(void) {
210 printf("%s trigger [OPTIONS] DEVPATH\n\n"
211 "Request events from the kernel.\n\n"
212 " -h --help Show this help\n"
213 " -V --version Show package version\n"
214 " -v --verbose Print the list of devices while running\n"
215 " -n --dry-run Do not actually trigger the events\n"
216 " -q --quiet Suppress error logging in triggering events\n"
217 " -t --type= Type of events to trigger\n"
218 " devices sysfs devices (default)\n"
219 " subsystems sysfs subsystems and drivers\n"
220 " -c --action=ACTION|help Event action value, default is \"change\"\n"
221 " -s --subsystem-match=SUBSYSTEM Trigger devices from a matching subsystem\n"
222 " -S --subsystem-nomatch=SUBSYSTEM Exclude devices from a matching subsystem\n"
223 " -a --attr-match=FILE[=VALUE] Trigger devices with a matching attribute\n"
224 " -A --attr-nomatch=FILE[=VALUE] Exclude devices with a matching attribute\n"
225 " -p --property-match=KEY=VALUE Trigger devices with a matching property\n"
226 " -g --tag-match=TAG Trigger devices with a matching tag\n"
227 " -y --sysname-match=NAME Trigger devices with this /sys path\n"
228 " --name-match=NAME Trigger devices with this /dev name\n"
229 " -b --parent-match=NAME Trigger devices with that parent device\n"
230 " --initialized-match Trigger devices that are already initialized\n"
231 " --initialized-nomatch Trigger devices that are not initialized yet\n"
232 " -w --settle Wait for the triggered events to complete\n"
233 " --wait-daemon[=SECONDS] Wait for udevd daemon to be initialized\n"
234 " before triggering uevents\n"
235 " --uuid Print synthetic uevent UUID\n"
236 " --prioritized-subsystem=SUBSYSTEM[,SUBSYSTEM…]\n"
237 " Trigger devices from a matching subsystem first\n",
238 program_invocation_short_name);
239
240 return 0;
241 }
242
trigger_main(int argc,char * argv[],void * userdata)243 int trigger_main(int argc, char *argv[], void *userdata) {
244 enum {
245 ARG_NAME = 0x100,
246 ARG_PING,
247 ARG_UUID,
248 ARG_PRIORITIZED_SUBSYSTEM,
249 ARG_INITIALIZED_MATCH,
250 ARG_INITIALIZED_NOMATCH,
251 };
252
253 static const struct option options[] = {
254 { "verbose", no_argument, NULL, 'v' },
255 { "dry-run", no_argument, NULL, 'n' },
256 { "quiet", no_argument, NULL, 'q' },
257 { "type", required_argument, NULL, 't' },
258 { "action", required_argument, NULL, 'c' },
259 { "subsystem-match", required_argument, NULL, 's' },
260 { "subsystem-nomatch", required_argument, NULL, 'S' },
261 { "attr-match", required_argument, NULL, 'a' },
262 { "attr-nomatch", required_argument, NULL, 'A' },
263 { "property-match", required_argument, NULL, 'p' },
264 { "tag-match", required_argument, NULL, 'g' },
265 { "sysname-match", required_argument, NULL, 'y' },
266 { "name-match", required_argument, NULL, ARG_NAME },
267 { "parent-match", required_argument, NULL, 'b' },
268 { "initialized-match", no_argument, NULL, ARG_INITIALIZED_MATCH },
269 { "initialized-nomatch", no_argument, NULL, ARG_INITIALIZED_NOMATCH },
270 { "settle", no_argument, NULL, 'w' },
271 { "wait-daemon", optional_argument, NULL, ARG_PING },
272 { "version", no_argument, NULL, 'V' },
273 { "help", no_argument, NULL, 'h' },
274 { "uuid", no_argument, NULL, ARG_UUID },
275 { "prioritized-subsystem", required_argument, NULL, ARG_PRIORITIZED_SUBSYSTEM },
276 {}
277 };
278 enum {
279 TYPE_DEVICES,
280 TYPE_SUBSYSTEMS,
281 TYPE_ALL,
282 } device_type = TYPE_DEVICES;
283 sd_device_action_t action = SD_DEVICE_CHANGE;
284 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
285 _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *m = NULL;
286 _cleanup_(sd_event_unrefp) sd_event *event = NULL;
287 _cleanup_hashmap_free_ Hashmap *settle_hashmap = NULL;
288 usec_t ping_timeout_usec = 5 * USEC_PER_SEC;
289 bool settle = false, ping = false;
290 int c, r;
291
292 if (running_in_chroot() > 0) {
293 log_info("Running in chroot, ignoring request.");
294 return 0;
295 }
296
297 r = sd_device_enumerator_new(&e);
298 if (r < 0)
299 return r;
300
301 r = sd_device_enumerator_allow_uninitialized(e);
302 if (r < 0)
303 return r;
304
305 while ((c = getopt_long(argc, argv, "vnqt:c:s:S:a:A:p:g:y:b:wVh", options, NULL)) >= 0) {
306 _cleanup_free_ char *buf = NULL;
307 const char *key, *val;
308
309 switch (c) {
310 case 'v':
311 arg_verbose = true;
312 break;
313 case 'n':
314 arg_dry_run = true;
315 break;
316 case 'q':
317 arg_quiet = true;
318 break;
319 case 't':
320 if (streq(optarg, "devices"))
321 device_type = TYPE_DEVICES;
322 else if (streq(optarg, "subsystems"))
323 device_type = TYPE_SUBSYSTEMS;
324 else if (streq(optarg, "all"))
325 device_type = TYPE_ALL;
326 else
327 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown type --type=%s", optarg);
328 break;
329 case 'c':
330 r = parse_device_action(optarg, &action);
331 if (r < 0)
332 return log_error_errno(r, "Unknown action '%s'", optarg);
333 if (r == 0)
334 return 0;
335 break;
336 case 's':
337 r = sd_device_enumerator_add_match_subsystem(e, optarg, true);
338 if (r < 0)
339 return log_error_errno(r, "Failed to add subsystem match '%s': %m", optarg);
340 break;
341 case 'S':
342 r = sd_device_enumerator_add_match_subsystem(e, optarg, false);
343 if (r < 0)
344 return log_error_errno(r, "Failed to add negative subsystem match '%s': %m", optarg);
345 break;
346 case 'a':
347 buf = keyval(optarg, &key, &val);
348 if (!buf)
349 return log_oom();
350 r = sd_device_enumerator_add_match_sysattr(e, key, val, true);
351 if (r < 0)
352 return log_error_errno(r, "Failed to add sysattr match '%s=%s': %m", key, val);
353 break;
354 case 'A':
355 buf = keyval(optarg, &key, &val);
356 if (!buf)
357 return log_oom();
358 r = sd_device_enumerator_add_match_sysattr(e, key, val, false);
359 if (r < 0)
360 return log_error_errno(r, "Failed to add negative sysattr match '%s=%s': %m", key, val);
361 break;
362 case 'p':
363 buf = keyval(optarg, &key, &val);
364 if (!buf)
365 return log_oom();
366 r = sd_device_enumerator_add_match_property(e, key, val);
367 if (r < 0)
368 return log_error_errno(r, "Failed to add property match '%s=%s': %m", key, val);
369 break;
370 case 'g':
371 r = sd_device_enumerator_add_match_tag(e, optarg);
372 if (r < 0)
373 return log_error_errno(r, "Failed to add tag match '%s': %m", optarg);
374 break;
375 case 'y':
376 r = sd_device_enumerator_add_match_sysname(e, optarg);
377 if (r < 0)
378 return log_error_errno(r, "Failed to add sysname match '%s': %m", optarg);
379 break;
380 case 'b': {
381 _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
382
383 r = find_device(optarg, "/sys", &dev);
384 if (r < 0)
385 return log_error_errno(r, "Failed to open the device '%s': %m", optarg);
386
387 r = device_enumerator_add_match_parent_incremental(e, dev);
388 if (r < 0)
389 return log_error_errno(r, "Failed to add parent match '%s': %m", optarg);
390 break;
391 }
392 case 'w':
393 settle = true;
394 break;
395
396 case ARG_NAME: {
397 _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
398
399 r = find_device(optarg, "/dev", &dev);
400 if (r < 0)
401 return log_error_errno(r, "Failed to open the device '%s': %m", optarg);
402
403 r = device_enumerator_add_match_parent_incremental(e, dev);
404 if (r < 0)
405 return log_error_errno(r, "Failed to add parent match '%s': %m", optarg);
406 break;
407 }
408
409 case ARG_PING:
410 ping = true;
411 if (optarg) {
412 r = parse_sec(optarg, &ping_timeout_usec);
413 if (r < 0)
414 log_error_errno(r, "Failed to parse timeout value '%s', ignoring: %m", optarg);
415 }
416 break;
417
418 case ARG_UUID:
419 arg_uuid = true;
420 break;
421
422 case ARG_PRIORITIZED_SUBSYSTEM: {
423 _cleanup_strv_free_ char **subsystems = NULL;
424
425 subsystems = strv_split(optarg, ",");
426 if (!subsystems)
427 return log_error_errno(r, "Failed to parse prioritized subsystem '%s': %m", optarg);
428
429 STRV_FOREACH(p, subsystems) {
430 r = device_enumerator_add_prioritized_subsystem(e, *p);
431 if (r < 0)
432 return log_error_errno(r, "Failed to add prioritized subsystem '%s': %m", *p);
433 }
434 break;
435 }
436 case ARG_INITIALIZED_MATCH:
437 case ARG_INITIALIZED_NOMATCH:
438 r = device_enumerator_add_match_is_initialized(e, c == ARG_INITIALIZED_MATCH ? MATCH_INITIALIZED_YES : MATCH_INITIALIZED_NO);
439 if (r < 0)
440 return log_error_errno(r, "Failed to set initialized filter: %m");
441 break;
442 case 'V':
443 return print_version();
444 case 'h':
445 return help();
446 case '?':
447 return -EINVAL;
448 default:
449 assert_not_reached();
450 }
451 }
452
453 if (ping) {
454 _cleanup_(udev_ctrl_unrefp) UdevCtrl *uctrl = NULL;
455
456 r = udev_ctrl_new(&uctrl);
457 if (r < 0)
458 return log_error_errno(r, "Failed to initialize udev control: %m");
459
460 r = udev_ctrl_send_ping(uctrl);
461 if (r < 0)
462 return log_error_errno(r, "Failed to connect to udev daemon: %m");
463
464 r = udev_ctrl_wait(uctrl, ping_timeout_usec);
465 if (r < 0)
466 return log_error_errno(r, "Failed to wait for daemon to reply: %m");
467 }
468
469 for (; optind < argc; optind++) {
470 _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
471
472 r = find_device(argv[optind], NULL, &dev);
473 if (r < 0)
474 return log_error_errno(r, "Failed to open the device '%s': %m", argv[optind]);
475
476 r = device_enumerator_add_match_parent_incremental(e, dev);
477 if (r < 0)
478 return log_error_errno(r, "Failed to add parent match '%s': %m", argv[optind]);
479 }
480
481 if (settle) {
482 settle_hashmap = hashmap_new(&path_hash_ops_free_free);
483 if (!settle_hashmap)
484 return log_oom();
485
486 r = sd_event_default(&event);
487 if (r < 0)
488 return log_error_errno(r, "Failed to get default event: %m");
489
490 r = sd_device_monitor_new(&m);
491 if (r < 0)
492 return log_error_errno(r, "Failed to create device monitor object: %m");
493
494 r = sd_device_monitor_attach_event(m, event);
495 if (r < 0)
496 return log_error_errno(r, "Failed to attach event to device monitor: %m");
497
498 r = sd_device_monitor_start(m, device_monitor_handler, settle_hashmap);
499 if (r < 0)
500 return log_error_errno(r, "Failed to start device monitor: %m");
501 }
502
503 switch (device_type) {
504 case TYPE_SUBSYSTEMS:
505 r = device_enumerator_scan_subsystems(e);
506 if (r < 0)
507 return log_error_errno(r, "Failed to scan subsystems: %m");
508 break;
509 case TYPE_DEVICES:
510 r = device_enumerator_scan_devices(e);
511 if (r < 0)
512 return log_error_errno(r, "Failed to scan devices: %m");
513 break;
514 case TYPE_ALL:
515 r = device_enumerator_scan_devices_and_subsystems(e);
516 if (r < 0)
517 return log_error_errno(r, "Failed to scan devices and subsystems: %m");
518 break;
519 default:
520 assert_not_reached();
521 }
522
523 r = exec_list(e, action, settle_hashmap);
524 if (r < 0)
525 return r;
526
527 if (event && !hashmap_isempty(settle_hashmap)) {
528 r = sd_event_loop(event);
529 if (r < 0)
530 return log_error_errno(r, "Event loop failed: %m");
531 }
532
533 return 0;
534 }
535