]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-device: use chase_symlinks() O_PATH fd
authorLennart Poettering <lennart@poettering.net>
Mon, 11 Apr 2022 20:02:23 +0000 (22:02 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 13 Apr 2022 12:40:09 +0000 (14:40 +0200)
chase_symlinks() can return its last O_PATH fd to us. Let's use that and
make the access() check a bit tighter by going via faccessat() on the
O_PATH fd.

This doesn't really change too much, but is nice in context of the next
commit, which uses the O_PATH fd in one other way.

src/libsystemd/sd-device/sd-device.c

index d31526fc222071e3429c3b0f8eb64c8b3458726d..eb50f592b7f4ba0769214f447860a9e41756a6bb 100644 (file)
@@ -150,7 +150,9 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
                                        _syspath);
 
         if (verify) {
-                r = chase_symlinks(_syspath, NULL, 0, &syspath, NULL);
+                _cleanup_close_ int fd = -1;
+
+                r = chase_symlinks(_syspath, NULL, 0, &syspath, &fd);
                 if (r == -ENOENT)
                          /* the device does not exist (any more?) */
                         return log_debug_errno(SYNTHETIC_ERRNO(ENODEV),
@@ -181,25 +183,28 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
                         path_simplify(syspath);
                 }
 
-                if (path_startswith(syspath,  "/sys/devices/")) {
-                        char *path;
+                if (path_startswith(syspath, "/sys/devices/")) {
+                        /* For proper devices, stricter rules apply: they must have a 'uevent' file,
+                         * otherwise we won't allow them */
 
-                        /* all 'devices' require an 'uevent' file */
-                        path = strjoina(syspath, "/uevent");
-                        if (access(path, F_OK) < 0) {
+                        if (faccessat(fd, "uevent", F_OK, 0) < 0) {
                                 if (errno == ENOENT)
-                                        /* This is not a valid device.
-                                         * Note, this condition is quite often satisfied when
-                                         * enumerating devices or finding a parent device.
+                                        /* This is not a valid device.  Note, this condition is quite often
+                                         * satisfied when enumerating devices or finding a parent device.
                                          * Hence, use log_trace_errno() here. */
                                         return log_trace_errno(SYNTHETIC_ERRNO(ENODEV),
-                                                               "sd-device: the uevent file \"%s\" does not exist.", path);
+                                                               "sd-device: the uevent file \"%s/uevent\" does not exist.", syspath);
 
-                                return log_debug_errno(errno, "sd-device: cannot access uevent file for %s: %m", syspath);
+                                return log_debug_errno(errno, "sd-device: cannot find uevent file for %s: %m", syspath);
                         }
                 } else {
-                        /* everything else just needs to be a directory */
-                        if (!is_dir(syspath, false))
+                        struct stat st;
+
+                        /* For everything else lax rules apply: they just need to be a directory */
+
+                        if (fstat(fd, &st) < 0)
+                                return log_debug_errno(errno, "sd-device: failed to check if syspath \"%s\" is a directory: %m", syspath);
+                        if (!S_ISDIR(st.st_mode))
                                 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV),
                                                        "sd-device: the syspath \"%s\" is not a directory.", syspath);
                 }