]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
lock-util: Add CLEANUP_UNPOSIX_UNLOCK()
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 8 Mar 2023 12:00:40 +0000 (13:00 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Fri, 10 Mar 2023 10:57:43 +0000 (11:57 +0100)
Also migrate the logic in dynamic-user.c to use the new cleanup
macro.

src/core/dynamic-user.c
src/shared/lock-util.c
src/shared/lock-util.h

index 9f4387a21b31c012ce397dd0abde531c00bae230..42936bf56761709ab0a963a001c04d3b81d37de1 100644 (file)
@@ -11,6 +11,7 @@
 #include "format-util.h"
 #include "fs-util.h"
 #include "io-util.h"
+#include "lock-util.h"
 #include "nscd-flush.h"
 #include "parse-util.h"
 #include "random-util.h"
@@ -362,27 +363,12 @@ static void unlink_uid_lock(int lock_fd, uid_t uid, const char *name) {
         (void) make_uid_symlinks(uid, name, false); /* remove direct lookup symlinks */
 }
 
-static int lockfp(int fd, int *fd_lock) {
-        if (lockf(fd, F_LOCK, 0) < 0)
-                return -errno;
-        *fd_lock = fd;
-        return 0;
-}
-
-static void unlockfp(int *fd_lock) {
-        if (*fd_lock < 0)
-                return;
-        lockf(*fd_lock, F_ULOCK, 0);
-        *fd_lock = -EBADF;
-}
-
 static int dynamic_user_realize(
                 DynamicUser *d,
                 char **suggested_dirs,
                 uid_t *ret_uid, gid_t *ret_gid,
                 bool is_user) {
 
-        _cleanup_(unlockfp) int storage_socket0_lock = -EBADF;
         _cleanup_close_ int uid_lock_fd = -EBADF;
         _cleanup_close_ int etc_passwd_lock_fd = -EBADF;
         uid_t num = UID_INVALID; /* a uid if is_user, and a gid otherwise */
@@ -397,10 +383,12 @@ static int dynamic_user_realize(
         /* Acquire a UID for the user name. This will allocate a UID for the user name if the user doesn't exist
          * yet. If it already exists its existing UID/GID will be reused. */
 
-        r = lockfp(d->storage_socket[0], &storage_socket0_lock);
+        r = unposix_lock(d->storage_socket[0], LOCK_EX);
         if (r < 0)
                 return r;
 
+        CLEANUP_UNPOSIX_UNLOCK(d->storage_socket[0]);
+
         r = dynamic_user_pop(d, &num, &uid_lock_fd);
         if (r < 0) {
                 int new_uid_lock_fd;
@@ -411,7 +399,9 @@ static int dynamic_user_realize(
 
                 /* OK, nothing stored yet, let's try to find something useful. While we are working on this release the
                  * lock however, so that nobody else blocks on our NSS lookups. */
-                unlockfp(&storage_socket0_lock);
+                r = unposix_lock(d->storage_socket[0], LOCK_UN);
+                if (r < 0)
+                        return r;
 
                 /* Let's see if a proper, static user or group by this name exists. Try to take the lock on
                  * /etc/passwd, if that fails with EROFS then /etc is read-only. In that case it's fine if we don't
@@ -461,7 +451,7 @@ static int dynamic_user_realize(
                 }
 
                 /* So, we found a working UID/lock combination. Let's see if we actually still need it. */
-                r = lockfp(d->storage_socket[0], &storage_socket0_lock);
+                r = unposix_lock(d->storage_socket[0], LOCK_EX);
                 if (r < 0) {
                         unlink_uid_lock(uid_lock_fd, num, d->name);
                         return r;
@@ -524,7 +514,6 @@ static int dynamic_user_realize(
 }
 
 int dynamic_user_current(DynamicUser *d, uid_t *ret) {
-        _cleanup_(unlockfp) int storage_socket0_lock = -EBADF;
         _cleanup_close_ int lock_fd = -EBADF;
         uid_t uid;
         int r;
@@ -534,10 +523,12 @@ int dynamic_user_current(DynamicUser *d, uid_t *ret) {
         /* Get the currently assigned UID for the user, if there's any. This simply pops the data from the
          * storage socket, and pushes it back in right-away. */
 
-        r = lockfp(d->storage_socket[0], &storage_socket0_lock);
+        r = unposix_lock(d->storage_socket[0], LOCK_EX);
         if (r < 0)
                 return r;
 
+        CLEANUP_UNPOSIX_UNLOCK(d->storage_socket[0]);
+
         r = dynamic_user_pop(d, &uid, &lock_fd);
         if (r < 0)
                 return r;
@@ -567,7 +558,6 @@ static DynamicUser* dynamic_user_unref(DynamicUser *d) {
 }
 
 static int dynamic_user_close(DynamicUser *d) {
-        _cleanup_(unlockfp) int storage_socket0_lock = -EBADF;
         _cleanup_close_ int lock_fd = -EBADF;
         uid_t uid;
         int r;
@@ -575,10 +565,12 @@ static int dynamic_user_close(DynamicUser *d) {
         /* Release the user ID, by releasing the lock on it, and emptying the storage socket. After this the
          * user is unrealized again, much like it was after it the DynamicUser object was first allocated. */
 
-        r = lockfp(d->storage_socket[0], &storage_socket0_lock);
+        r = unposix_lock(d->storage_socket[0], LOCK_EX);
         if (r < 0)
                 return r;
 
+        CLEANUP_UNPOSIX_UNLOCK(d->storage_socket[0]);
+
         r = dynamic_user_pop(d, &uid, &lock_fd);
         if (r == -EAGAIN)
                 /* User wasn't realized yet, nothing to do. */
index bbbd31464377e4912b6811e9f43b546ca89a663b..2d8ed1a2b353db4970a30667384e124977144908 100644 (file)
@@ -149,3 +149,13 @@ int unposix_lock(int fd, int operation) {
 
         return r;
 }
+
+void unposix_unlockpp(int **fd) {
+        assert(fd);
+
+        if (!*fd || **fd < 0)
+                return;
+
+        (void) unposix_lock(**fd, LOCK_UN);
+        *fd = NULL;
+}
index 66f86351331c7a1fe21729c8acd5721347944ad4..e8d4c24874f11b210e8aee8901d34ee67cb457ae 100644 (file)
@@ -15,3 +15,8 @@ void release_lock_file(LockFile *f);
 
 /* Open File Description locks with the same interface as flock(). */
 int unposix_lock(int fd, int operation);
+
+void unposix_unlockpp(int **fd);
+
+#define CLEANUP_UNPOSIX_UNLOCK(fd)                                   \
+        _cleanup_(unposix_unlockpp) _unused_ int *CONCATENATE(_cleanup_unposix_unlock_, UNIQ) = &(fd)