diff options
-rw-r--r-- | src/udev/udev-node.c | 62 | ||||
-rw-r--r-- | src/udev/udev-node.h | 7 | ||||
-rw-r--r-- | src/udev/udev-rules.c | 70 |
3 files changed, 71 insertions, 68 deletions
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c index 493feffe00..deacbc31c5 100644 --- a/src/udev/udev-node.c +++ b/src/udev/udev-node.c @@ -13,6 +13,7 @@ #include "device-private.h" #include "device-util.h" #include "dirent-util.h" +#include "escape.h" #include "fd-util.h" #include "format-util.h" #include "fs-util.h" @@ -718,3 +719,64 @@ int udev_node_apply_permissions( return udev_node_apply_permissions_impl(dev, node_fd, devnode, apply_mac, mode, uid, gid, seclabel_list); } + +int static_node_apply_permissions( + const char *name, + mode_t mode, + uid_t uid, + gid_t gid, + char **tags) { + + _cleanup_free_ char *unescaped_filename = NULL; + _cleanup_close_ int node_fd = -1; + const char *devnode; + struct stat stats; + int r; + + assert(name); + + if (uid == UID_INVALID && gid == GID_INVALID && mode == MODE_INVALID && !tags) + return 0; + + devnode = strjoina("/dev/", name); + + node_fd = open(devnode, O_PATH|O_CLOEXEC); + if (node_fd < 0) { + if (errno != ENOENT) + return log_error_errno(errno, "Failed to open %s: %m", devnode); + return 0; + } + + if (fstat(node_fd, &stats) < 0) + return log_error_errno(errno, "Failed to stat %s: %m", devnode); + + if (!S_ISBLK(stats.st_mode) && !S_ISCHR(stats.st_mode)) { + log_warning("%s is neither block nor character device, ignoring.", devnode); + return 0; + } + + if (!strv_isempty(tags)) { + unescaped_filename = xescape(name, "/."); + if (!unescaped_filename) + return log_oom(); + } + + /* export the tags to a directory as symlinks, allowing otherwise dead nodes to be tagged */ + STRV_FOREACH(t, tags) { + _cleanup_free_ char *p = NULL; + + p = path_join("/run/udev/static_node-tags/", *t, unescaped_filename); + if (!p) + return log_oom(); + + r = mkdir_parents(p, 0755); + if (r < 0) + return log_error_errno(r, "Failed to create parent directory for %s: %m", p); + + r = symlink(devnode, p); + if (r < 0 && errno != EEXIST) + return log_error_errno(errno, "Failed to create symlink %s -> %s: %m", p, devnode); + } + + return udev_node_apply_permissions_impl(NULL, node_fd, devnode, false, mode, uid, gid, NULL); +} diff --git a/src/udev/udev-node.h b/src/udev/udev-node.h index a34af77146..86a829545a 100644 --- a/src/udev/udev-node.h +++ b/src/udev/udev-node.h @@ -15,6 +15,13 @@ int udev_node_apply_permissions( uid_t uid, gid_t gid, OrderedHashmap *seclabel_list); +int static_node_apply_permissions( + const char *name, + mode_t mode, + uid_t uid, + gid_t gid, + char **tags); + int udev_node_remove(sd_device *dev); int udev_node_update(sd_device *dev, sd_device *dev_old); diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index b46cb0f906..1c20775f08 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -9,7 +9,6 @@ #include "device-private.h" #include "device-util.h" #include "dirent-util.h" -#include "escape.h" #include "fd-util.h" #include "fileio.h" #include "format-util.h" @@ -30,6 +29,7 @@ #include "udev-builtin.h" #include "udev-event.h" #include "udev-netlink.h" +#include "udev-node.h" #include "udev-rules.h" #include "udev-util.h" #include "user-util.h" @@ -2536,72 +2536,6 @@ int udev_rules_apply_to_event( return 0; } -static int apply_static_dev_perms(const char *devnode, uid_t uid, gid_t gid, mode_t mode, char **tags) { - char device_node[UDEV_PATH_SIZE], tags_dir[UDEV_PATH_SIZE], tag_symlink[UDEV_PATH_SIZE]; - _cleanup_free_ char *unescaped_filename = NULL; - struct stat stats; - int r; - - assert(devnode); - - if (uid == UID_INVALID && gid == GID_INVALID && mode == MODE_INVALID && !tags) - return 0; - - strscpyl(device_node, sizeof(device_node), "/dev/", devnode, NULL); - if (stat(device_node, &stats) < 0) { - if (errno != ENOENT) - return log_error_errno(errno, "Failed to stat %s: %m", device_node); - return 0; - } - - if (!S_ISBLK(stats.st_mode) && !S_ISCHR(stats.st_mode)) { - log_warning("%s is neither block nor character device, ignoring.", device_node); - return 0; - } - - if (!strv_isempty(tags)) { - unescaped_filename = xescape(devnode, "/."); - if (!unescaped_filename) - return log_oom(); - } - - /* export the tags to a directory as symlinks, allowing otherwise dead nodes to be tagged */ - STRV_FOREACH(t, tags) { - strscpyl(tags_dir, sizeof(tags_dir), "/run/udev/static_node-tags/", *t, "/", NULL); - r = mkdir_p(tags_dir, 0755); - if (r < 0) - return log_error_errno(r, "Failed to create %s: %m", tags_dir); - - strscpyl(tag_symlink, sizeof(tag_symlink), tags_dir, unescaped_filename, NULL); - r = symlink(device_node, tag_symlink); - if (r < 0 && errno != EEXIST) - return log_error_errno(errno, "Failed to create symlink %s -> %s: %m", - tag_symlink, device_node); - } - - /* don't touch the permissions if only the tags were set */ - if (uid == UID_INVALID && gid == GID_INVALID && mode == MODE_INVALID) - return 0; - - if (mode == MODE_INVALID) - mode = gid_is_valid(gid) ? 0660 : 0600; - if (!uid_is_valid(uid)) - uid = 0; - if (!gid_is_valid(gid)) - gid = 0; - - r = chmod_and_chown(device_node, mode, uid, gid); - if (r == -ENOENT) - return 0; - if (r < 0) - return log_error_errno(r, "Failed to chown '%s' %u %u: %m", device_node, uid, gid); - else - log_debug("chown '%s' %u:%u with mode %#o", device_node, uid, gid, mode); - - (void) utimensat(AT_FDCWD, device_node, NULL, 0); - return 0; -} - static int udev_rule_line_apply_static_dev_perms(UdevRuleLine *rule_line) { _cleanup_strv_free_ char **tags = NULL; uid_t uid = UID_INVALID; @@ -2626,7 +2560,7 @@ static int udev_rule_line_apply_static_dev_perms(UdevRuleLine *rule_line) { if (r < 0) return log_oom(); } else if (token->type == TK_A_OPTIONS_STATIC_NODE) { - r = apply_static_dev_perms(token->value, uid, gid, mode, tags); + r = static_node_apply_permissions(token->value, mode, uid, gid, tags); if (r < 0) return r; } |