]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/udev/udev-node.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
7 #include "alloc-util.h"
8 #include "device-private.h"
9 #include "device-util.h"
10 #include "devnum-util.h"
11 #include "dirent-util.h"
15 #include "format-util.h"
17 #include "hexdecoct.h"
19 #include "mkdir-label.h"
20 #include "parse-util.h"
21 #include "path-util.h"
22 #include "selinux-util.h"
23 #include "smack-util.h"
24 #include "stat-util.h"
25 #include "string-util.h"
26 #include "udev-node.h"
27 #include "user-util.h"
29 #define UDEV_NODE_HASH_KEY SD_ID128_MAKE(b9,6a,f1,ce,40,31,44,1a,9e,19,ec,8b,ae,f3,e3,2f)
31 int udev_node_cleanup(void) {
32 _cleanup_closedir_
DIR *dir
= NULL
;
34 /* This must not be called when any workers exist. It would cause a race between mkdir() called
35 * by stack_directory_lock() and unlinkat() called by this. */
37 dir
= opendir("/run/udev/links");
42 return log_debug_errno(errno
, "Failed to open directory '/run/udev/links', ignoring: %m");
45 FOREACH_DIRENT_ALL(de
, dir
, break) {
46 _cleanup_free_
char *lockfile
= NULL
;
48 if (de
->d_name
[0] == '.')
51 if (de
->d_type
!= DT_DIR
)
54 /* As commented in the above, this is called when no worker exists, hence the file is not
55 * locked. On a later uevent, the lock file will be created if necessary. So, we can safely
56 * remove the file now. */
57 lockfile
= path_join(de
->d_name
, ".lock");
59 return log_oom_debug();
61 if (unlinkat(dirfd(dir
), lockfile
, 0) < 0 && errno
!= ENOENT
) {
62 log_debug_errno(errno
, "Failed to remove '/run/udev/links/%s', ignoring: %m", lockfile
);
66 if (unlinkat(dirfd(dir
), de
->d_name
, AT_REMOVEDIR
) < 0 && errno
!= ENOTEMPTY
)
67 log_debug_errno(errno
, "Failed to remove '/run/udev/links/%s', ignoring: %m", de
->d_name
);
73 static int node_symlink(sd_device
*dev
, const char *devnode
, const char *slink
) {
81 r
= sd_device_get_devname(dev
, &devnode
);
83 return log_device_debug_errno(dev
, r
, "Failed to get device node: %m");
86 if (lstat(slink
, &st
) >= 0) {
87 if (!S_ISLNK(st
.st_mode
))
88 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(EEXIST
),
89 "Conflicting inode '%s' found, symlink to '%s' will not be created.",
91 } else if (errno
!= ENOENT
)
92 return log_device_debug_errno(dev
, errno
, "Failed to lstat() '%s': %m", slink
);
94 r
= mkdir_parents_label(slink
, 0755);
96 return log_device_debug_errno(dev
, r
, "Failed to create parent directory of '%s': %m", slink
);
98 /* use relative link */
99 r
= symlink_atomic_full_label(devnode
, slink
, /* make_relative = */ true);
101 return log_device_debug_errno(dev
, r
, "Failed to create symlink '%s' to '%s': %m", slink
, devnode
);
103 log_device_debug(dev
, "Successfully created symlink '%s' to '%s'", slink
, devnode
);
107 static int stack_directory_read_one(int dirfd
, const char *id
, char **devnode
, int *priority
) {
108 _cleanup_free_
char *buf
= NULL
;
116 /* First, let's try to read the entry with the new format, which should replace the old format pretty
119 r
= readlinkat_malloc(dirfd
, id
, &buf
);
123 /* With the new format, the devnode and priority can be obtained from symlink itself. */
125 colon
= strchr(buf
, ':');
126 if (!colon
|| colon
== buf
)
131 /* Of course, this check is racy, but it is not necessary to be perfect. Even if the device
132 * node will be removed after this check, we will receive 'remove' uevent, and the invalid
133 * symlink will be removed during processing the event. The check is just for shortening the
134 * timespan that the symlink points to a non-existing device node. */
135 if (access(colon
+ 1, F_OK
) < 0)
138 r
= safe_atoi(buf
, &tmp_prio
);
142 if (*devnode
&& tmp_prio
<= *priority
)
143 return 0; /* Unchanged */
145 r
= free_and_strdup(devnode
, colon
+ 1);
149 } else if (r
== -EINVAL
) { /* Not a symlink ? try the old format */
150 _cleanup_(sd_device_unrefp
) sd_device
*dev
= NULL
;
153 /* Old format. The devnode and priority must be obtained from uevent and udev database. */
155 r
= sd_device_new_from_device_id(&dev
, id
);
159 r
= device_get_devlink_priority(dev
, &tmp_prio
);
163 if (*devnode
&& tmp_prio
<= *priority
)
164 return 0; /* Unchanged */
166 r
= sd_device_get_devname(dev
, &val
);
170 r
= free_and_strdup(devnode
, val
);
175 return r
== -ENOENT
? -ENODEV
: r
;
177 *priority
= tmp_prio
;
178 return 1; /* Updated */
181 static int stack_directory_find_prioritized_devnode(sd_device
*dev
, int dirfd
, bool add
, char **ret
) {
182 _cleanup_closedir_
DIR *dir
= NULL
;
183 _cleanup_free_
char *devnode
= NULL
;
191 /* Find device node of device with highest priority. This returns 1 if a device found, 0 if no
192 * device found, or a negative errno on error. */
197 r
= device_get_devlink_priority(dev
, &priority
);
201 r
= sd_device_get_devname(dev
, &n
);
210 dir
= xopendirat(dirfd
, ".", O_NOFOLLOW
);
214 r
= device_get_device_id(dev
, &id
);
218 FOREACH_DIRENT(de
, dir
, break) {
221 if (streq(de
->d_name
, id
))
224 r
= stack_directory_read_one(dirfd
, de
->d_name
, &devnode
, &priority
);
225 if (r
< 0 && r
!= -ENODEV
)
226 log_debug_errno(r
, "Failed to read '%s', ignoring: %m", de
->d_name
);
229 *ret
= TAKE_PTR(devnode
);
233 static int stack_directory_update(sd_device
*dev
, int fd
, bool add
) {
240 r
= device_get_device_id(dev
, &id
);
245 _cleanup_free_
char *data
= NULL
, *buf
= NULL
;
249 r
= sd_device_get_devname(dev
, &devname
);
253 r
= device_get_devlink_priority(dev
, &priority
);
257 if (asprintf(&data
, "%i:%s", priority
, devname
) < 0)
260 if (readlinkat_malloc(fd
, id
, &buf
) >= 0 && streq(buf
, data
))
261 return 0; /* Unchanged. */
263 (void) unlinkat(fd
, id
, 0);
265 if (symlinkat(data
, fd
, id
) < 0)
269 if (unlinkat(fd
, id
, 0) < 0) {
271 return 0; /* Unchanged. */
276 return 1; /* Updated. */
279 size_t udev_node_escape_path(const char *src
, char *dest
, size_t size
) {
287 for (i
= 0, j
= 0; src
[i
] != '\0'; i
++) {
289 if (j
+4 >= size
- 12 + 1)
291 memcpy(&dest
[j
], "\\x2f", 4);
293 } else if (src
[i
] == '\\') {
294 if (j
+4 >= size
- 12 + 1)
296 memcpy(&dest
[j
], "\\x5c", 4);
299 if (j
+1 >= size
- 12 + 1)
309 /* If the input path is too long to encode as a filename, then let's suffix with a string
310 * generated from the hash of the path. */
312 h
= siphash24_string(src
, UDEV_NODE_HASH_KEY
.bytes
);
314 for (unsigned k
= 0; k
<= 10; k
++)
315 dest
[size
- k
- 2] = urlsafe_base64char((h
>> (k
* 6)) & 63);
317 dest
[size
- 1] = '\0';
321 static int stack_directory_get_name(const char *slink
, char **ret
) {
322 _cleanup_free_
char *s
= NULL
, *dirname
= NULL
;
323 char name_enc
[NAME_MAX
+1];
335 if (!path_is_normalized(s
))
338 name
= path_startswith(s
, "/dev");
339 if (empty_or_root(name
))
342 udev_node_escape_path(name
, name_enc
, sizeof(name_enc
));
344 dirname
= path_join("/run/udev/links", name_enc
);
348 *ret
= TAKE_PTR(dirname
);
352 static int stack_directory_open(sd_device
*dev
, const char *slink
, int *ret_dirfd
, int *ret_lockfd
) {
353 _cleanup_close_
int dirfd
= -EBADF
, lockfd
= -EBADF
;
354 _cleanup_free_
char *dirname
= NULL
;
362 r
= stack_directory_get_name(slink
, &dirname
);
364 return log_device_debug_errno(dev
, r
, "Failed to build stack directory name for '%s': %m", slink
);
366 r
= mkdir_parents(dirname
, 0755);
368 return log_device_debug_errno(dev
, r
, "Failed to create stack directory '%s': %m", dirname
);
370 dirfd
= open_mkdir_at(AT_FDCWD
, dirname
, O_CLOEXEC
| O_DIRECTORY
| O_NOFOLLOW
| O_RDONLY
, 0755);
372 return log_device_debug_errno(dev
, dirfd
, "Failed to open stack directory '%s': %m", dirname
);
374 lockfd
= openat(dirfd
, ".lock", O_CLOEXEC
| O_NOFOLLOW
| O_RDONLY
| O_CREAT
, 0600);
376 return log_device_debug_errno(dev
, errno
, "Failed to create lock file for stack directory '%s': %m", dirname
);
378 if (flock(lockfd
, LOCK_EX
) < 0)
379 return log_device_debug_errno(dev
, errno
, "Failed to place a lock on lock file for %s: %m", dirname
);
381 *ret_dirfd
= TAKE_FD(dirfd
);
382 *ret_lockfd
= TAKE_FD(lockfd
);
386 static int link_update(sd_device
*dev
, const char *slink
, bool add
) {
387 _cleanup_close_
int dirfd
= -EBADF
, lockfd
= -EBADF
;
388 _cleanup_free_
char *devnode
= NULL
;
394 r
= stack_directory_open(dev
, slink
, &dirfd
, &lockfd
);
398 r
= stack_directory_update(dev
, dirfd
, add
);
400 return log_device_debug_errno(dev
, r
, "Failed to update stack directory for '%s': %m", slink
);
402 r
= stack_directory_find_prioritized_devnode(dev
, dirfd
, add
, &devnode
);
404 return log_device_debug_errno(dev
, r
, "Failed to determine device node with the highest priority for '%s': %m", slink
);
406 return node_symlink(dev
, devnode
, slink
);
408 log_device_debug(dev
, "No reference left for '%s', removing", slink
);
410 if (unlink(slink
) < 0 && errno
!= ENOENT
)
411 log_device_debug_errno(dev
, errno
, "Failed to remove '%s', ignoring: %m", slink
);
413 (void) rmdir_parents(slink
, "/dev");
418 static int device_get_devpath_by_devnum(sd_device
*dev
, char **ret
) {
419 const char *subsystem
;
426 r
= sd_device_get_subsystem(dev
, &subsystem
);
430 r
= sd_device_get_devnum(dev
, &devnum
);
434 return device_path_make_major_minor(streq(subsystem
, "block") ? S_IFBLK
: S_IFCHR
, devnum
, ret
);
437 int udev_node_update(sd_device
*dev
, sd_device
*dev_old
) {
438 _cleanup_free_
char *filename
= NULL
;
445 /* update possible left-over symlinks */
446 FOREACH_DEVICE_DEVLINK(dev_old
, devlink
) {
447 /* check if old link name still belongs to this device */
448 if (device_has_devlink(dev
, devlink
))
451 log_device_debug(dev
,
452 "Removing/updating old device symlink '%s', which is no longer belonging to this device.",
455 r
= link_update(dev
, devlink
, /* add = */ false);
457 log_device_warning_errno(dev
, r
,
458 "Failed to remove/update device symlink '%s', ignoring: %m",
462 /* create/update symlinks, add symlinks to name index */
463 FOREACH_DEVICE_DEVLINK(dev
, devlink
) {
464 r
= link_update(dev
, devlink
, /* add = */ true);
466 log_device_warning_errno(dev
, r
,
467 "Failed to create/update device symlink '%s', ignoring: %m",
471 r
= device_get_devpath_by_devnum(dev
, &filename
);
473 return log_device_debug_errno(dev
, r
, "Failed to get device path: %m");
475 /* always add /dev/{block,char}/$major:$minor */
476 r
= node_symlink(dev
, NULL
, filename
);
478 return log_device_warning_errno(dev
, r
, "Failed to create device symlink '%s': %m", filename
);
483 int udev_node_remove(sd_device
*dev
) {
484 _cleanup_free_
char *filename
= NULL
;
490 /* remove/update symlinks, remove symlinks from name index */
491 FOREACH_DEVICE_DEVLINK(dev
, devlink
) {
492 r
= link_update(dev
, devlink
, /* add = */ false);
494 log_device_warning_errno(dev
, r
,
495 "Failed to remove/update device symlink '%s', ignoring: %m",
499 r
= device_get_devpath_by_devnum(dev
, &filename
);
501 return log_device_debug_errno(dev
, r
, "Failed to get device path: %m");
503 /* remove /dev/{block,char}/$major:$minor */
504 if (unlink(filename
) < 0 && errno
!= ENOENT
)
505 return log_device_debug_errno(dev
, errno
, "Failed to remove '%s': %m", filename
);
510 static int udev_node_apply_permissions_impl(
511 sd_device
*dev
, /* can be NULL, only used for logging. */
518 OrderedHashmap
*seclabel_list
) {
520 bool apply_mode
, apply_uid
, apply_gid
;
524 assert(node_fd
>= 0);
527 if (fstat(node_fd
, &stats
) < 0)
528 return log_device_debug_errno(dev
, errno
, "cannot stat() node %s: %m", devnode
);
530 /* If group is set, but mode is not set, "upgrade" mode for the group. */
531 if (mode
== MODE_INVALID
&& gid_is_valid(gid
) && gid
> 0)
534 apply_mode
= mode
!= MODE_INVALID
&& (stats
.st_mode
& 0777) != (mode
& 0777);
535 apply_uid
= uid_is_valid(uid
) && stats
.st_uid
!= uid
;
536 apply_gid
= gid_is_valid(gid
) && stats
.st_gid
!= gid
;
538 if (apply_mode
|| apply_uid
|| apply_gid
|| apply_mac
) {
539 bool selinux
= false, smack
= false;
540 const char *name
, *label
;
542 if (apply_mode
|| apply_uid
|| apply_gid
) {
543 log_device_debug(dev
, "Setting permissions %s, uid=" UID_FMT
", gid=" GID_FMT
", mode=%#o",
545 uid_is_valid(uid
) ? uid
: stats
.st_uid
,
546 gid_is_valid(gid
) ? gid
: stats
.st_gid
,
547 mode
!= MODE_INVALID
? mode
& 0777 : stats
.st_mode
& 0777);
549 r
= fchmod_and_chown(node_fd
, mode
, uid
, gid
);
551 log_device_full_errno(dev
, r
== -ENOENT
? LOG_DEBUG
: LOG_ERR
, r
,
552 "Failed to set owner/mode of %s to uid=" UID_FMT
553 ", gid=" GID_FMT
", mode=%#o: %m",
555 uid_is_valid(uid
) ? uid
: stats
.st_uid
,
556 gid_is_valid(gid
) ? gid
: stats
.st_gid
,
557 mode
!= MODE_INVALID
? mode
& 0777 : stats
.st_mode
& 0777);
559 log_device_debug(dev
, "Preserve permissions of %s, uid=" UID_FMT
", gid=" GID_FMT
", mode=%#o",
561 uid_is_valid(uid
) ? uid
: stats
.st_uid
,
562 gid_is_valid(gid
) ? gid
: stats
.st_gid
,
563 mode
!= MODE_INVALID
? mode
& 0777 : stats
.st_mode
& 0777);
565 /* apply SECLABEL{$module}=$label */
566 ORDERED_HASHMAP_FOREACH_KEY(label
, name
, seclabel_list
) {
569 if (streq(name
, "selinux")) {
572 q
= mac_selinux_apply_fd(node_fd
, devnode
, label
);
574 log_device_full_errno(dev
, q
== -ENOENT
? LOG_DEBUG
: LOG_ERR
, q
,
575 "SECLABEL: failed to set SELinux label '%s': %m", label
);
577 log_device_debug(dev
, "SECLABEL: set SELinux label '%s'", label
);
579 } else if (streq(name
, "smack")) {
582 q
= mac_smack_apply_fd(node_fd
, SMACK_ATTR_ACCESS
, label
);
584 log_device_full_errno(dev
, q
== -ENOENT
? LOG_DEBUG
: LOG_ERR
, q
,
585 "SECLABEL: failed to set SMACK label '%s': %m", label
);
587 log_device_debug(dev
, "SECLABEL: set SMACK label '%s'", label
);
590 log_device_error(dev
, "SECLABEL: unknown subsystem, ignoring '%s'='%s'", name
, label
);
593 /* set the defaults */
595 (void) mac_selinux_fix_full(node_fd
, NULL
, devnode
, LABEL_IGNORE_ENOENT
);
597 (void) mac_smack_apply_fd(node_fd
, SMACK_ATTR_ACCESS
, NULL
);
600 /* always update timestamp when we re-use the node, like on media change events */
601 r
= futimens_opath(node_fd
, NULL
);
603 log_device_debug_errno(dev
, r
, "Failed to adjust timestamp of node %s: %m", devnode
);
608 int udev_node_apply_permissions(
614 OrderedHashmap
*seclabel_list
) {
617 _cleanup_close_
int node_fd
= -EBADF
;
622 r
= sd_device_get_devname(dev
, &devnode
);
624 return log_device_debug_errno(dev
, r
, "Failed to get devname: %m");
626 node_fd
= sd_device_open(dev
, O_PATH
|O_CLOEXEC
);
628 if (ERRNO_IS_DEVICE_ABSENT(node_fd
)) {
629 log_device_debug_errno(dev
, node_fd
, "Device node %s is missing, skipping handling.", devnode
);
630 return 0; /* This is necessarily racey, so ignore missing the device */
633 return log_device_debug_errno(dev
, node_fd
, "Cannot open node %s: %m", devnode
);
636 return udev_node_apply_permissions_impl(dev
, node_fd
, devnode
, apply_mac
, mode
, uid
, gid
, seclabel_list
);
639 int static_node_apply_permissions(
646 _cleanup_free_
char *unescaped_filename
= NULL
;
647 _cleanup_close_
int node_fd
= -EBADF
;
654 if (uid
== UID_INVALID
&& gid
== GID_INVALID
&& mode
== MODE_INVALID
&& !tags
)
657 devnode
= strjoina("/dev/", name
);
659 node_fd
= open(devnode
, O_PATH
|O_CLOEXEC
);
662 return log_error_errno(errno
, "Failed to open %s: %m", devnode
);
666 if (fstat(node_fd
, &stats
) < 0)
667 return log_error_errno(errno
, "Failed to stat %s: %m", devnode
);
669 if (!S_ISBLK(stats
.st_mode
) && !S_ISCHR(stats
.st_mode
)) {
670 log_warning("%s is neither block nor character device, ignoring.", devnode
);
674 if (!strv_isempty(tags
)) {
675 unescaped_filename
= xescape(name
, "/.");
676 if (!unescaped_filename
)
680 /* export the tags to a directory as symlinks, allowing otherwise dead nodes to be tagged */
681 STRV_FOREACH(t
, tags
) {
682 _cleanup_free_
char *p
= NULL
;
684 p
= path_join("/run/udev/static_node-tags/", *t
, unescaped_filename
);
688 r
= mkdir_parents(p
, 0755);
690 return log_error_errno(r
, "Failed to create parent directory for %s: %m", p
);
692 r
= symlink(devnode
, p
);
693 if (r
< 0 && errno
!= EEXIST
)
694 return log_error_errno(errno
, "Failed to create symlink %s -> %s: %m", p
, devnode
);
697 return udev_node_apply_permissions_impl(NULL
, node_fd
, devnode
, false, mode
, uid
, gid
, NULL
);