]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
fs-util,tmpfiles: fix error handling of fchmod_opath()
authorLennart Poettering <lennart@poettering.net>
Wed, 9 Sep 2020 18:35:33 +0000 (20:35 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 10 Sep 2020 10:47:50 +0000 (12:47 +0200)
When 4dfaa528d45 was first commited its callers relied on `errno` instead of the
return value for error reporting. Which worked fine, since internally
under all conditions base were set — even if ugly and not inline with
our coding style. Things then got broken in
f8606626ed3c2582e06543550d58fe9886cdca5f where suddenly additional
syscalls might end up being done in the function, thus corrupting `errno`.

src/basic/fs-util.c
src/tmpfiles/tmpfiles.c

index 030789d7169a061343ccbba6dfae6000356a0df5..7f8b8b22b3fa12eea3ce0d1a47b6b8e74a8b2243 100644 (file)
@@ -229,6 +229,7 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
 int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) {
         bool do_chown, do_chmod;
         struct stat st;
+        int r;
 
         /* Change ownership and access mode of the specified fd. Tries to do so safely, ensuring that at no
          * point in time the access mode is above the old access mode under the old ownership or the new
@@ -259,18 +260,22 @@ int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) {
         if (do_chown && do_chmod) {
                 mode_t minimal = st.st_mode & mode; /* the subset of the old and the new mask */
 
-                if (((minimal ^ st.st_mode) & 07777) != 0)
-                        if (fchmod_opath(fd, minimal & 07777) < 0)
-                                return -errno;
+                if (((minimal ^ st.st_mode) & 07777) != 0) {
+                        r = fchmod_opath(fd, minimal & 07777);
+                        if (r < 0)
+                                return r;
+                }
         }
 
         if (do_chown)
                 if (fchownat(fd, "", uid, gid, AT_EMPTY_PATH) < 0)
                         return -errno;
 
-        if (do_chmod)
-                if (fchmod_opath(fd, mode & 07777) < 0)
-                        return -errno;
+        if (do_chmod) {
+                r = fchmod_opath(fd, mode & 07777);
+                if (r < 0)
+                        return r;
+        }
 
         return do_chown || do_chmod;
 }
index 5a0a5a58672933364edd56f114431ad53ba4e259..61571a45eebb023d272b5b9903a4fc8eb7d2550d 100644 (file)
@@ -836,6 +836,7 @@ static int fd_set_perms(Item *i, int fd, const char *path, const struct stat *st
         struct stat stbuf;
         mode_t new_mode;
         bool do_chown;
+        int r;
 
         assert(i);
         assert(fd);
@@ -881,8 +882,9 @@ static int fd_set_perms(Item *i, int fd, const char *path, const struct stat *st
                                 log_debug("\"%s\" matches temporary mode %o already.", path, m);
                         else {
                                 log_debug("Temporarily changing \"%s\" to mode %o.", path, m);
-                                if (fchmod_opath(fd, m) < 0)
-                                        return log_error_errno(errno, "fchmod() of %s failed: %m", path);
+                                r = fchmod_opath(fd, m);
+                                if (r < 0)
+                                        return log_error_errno(r, "fchmod() of %s failed: %m", path);
                         }
                 }
         }
@@ -913,8 +915,9 @@ static int fd_set_perms(Item *i, int fd, const char *path, const struct stat *st
                                 log_debug("\"%s\" matches mode %o already.", path, new_mode);
                         else {
                                 log_debug("Changing \"%s\" to mode %o.", path, new_mode);
-                                if (fchmod_opath(fd, new_mode) < 0)
-                                        return log_error_errno(errno, "fchmod() of %s failed: %m", path);
+                                r = fchmod_opath(fd, new_mode);
+                                if (r < 0)
+                                        return log_error_errno(r, "fchmod() of %s failed: %m", path);
                         }
                 }
         }