]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
socket-util: introduce type-safe, dereferencing wrapper CMSG_FIND_DATA around cmsg_find() 15570/head
authorLennart Poettering <lennart@poettering.net>
Fri, 17 Apr 2020 09:52:48 +0000 (11:52 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 23 Apr 2020 17:41:15 +0000 (19:41 +0200)
let's take this once step further, and add type-safety to cmsg_find(),
and imply the CMSG_DATA() macro for finding the cmsg payload.

src/basic/socket-util.h
src/import/importd.c
src/journal/journald-stream.c
src/nspawn/nspawn.c
src/shared/ask-password-api.c
src/udev/udevd.c

index 95643135df7cbca6db0b3e734c94eaf9680e41f6..fba4efef814ea5289e2e4644ae2877761073ee5b 100644 (file)
@@ -158,6 +158,14 @@ int flush_accept(int fd);
 
 struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length);
 
+/* Type-safe, dereferencing version of cmsg_find() */
+#define CMSG_FIND_DATA(mh, level, type, ctype) \
+        ({                                                            \
+                struct cmsghdr *_found;                               \
+                _found = cmsg_find(mh, level, type, CMSG_LEN(sizeof(ctype))); \
+                (ctype*) (_found ? CMSG_DATA(_found) : NULL);         \
+        })
+
 /*
  * Certain hardware address types (e.g Infiniband) do not fit into sll_addr
  * (8 bytes) and run over the structure. This macro returns the correct size that
index 340b12ecd5c9044d2c6c776529ce8aa4b7241179..417e686bb9daa9d8bddc11816708f9d8e5ed29b3 100644 (file)
@@ -557,9 +557,8 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void
                 .msg_control = &control,
                 .msg_controllen = sizeof(control),
         };
-        struct ucred *ucred = NULL;
+        struct ucred *ucred;
         Manager *m = userdata;
-        struct cmsghdr *cmsg;
         char *p, *e;
         Transfer *t;
         Iterator i;
@@ -574,17 +573,12 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void
 
         cmsg_close_all(&msghdr);
 
-        CMSG_FOREACH(cmsg, &msghdr)
-                if (cmsg->cmsg_level == SOL_SOCKET &&
-                    cmsg->cmsg_type == SCM_CREDENTIALS &&
-                    cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
-                        ucred = (struct ucred*) CMSG_DATA(cmsg);
-
         if (msghdr.msg_flags & MSG_TRUNC) {
                 log_warning("Got overly long notification datagram, ignoring.");
                 return 0;
         }
 
+        ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
         if (!ucred || ucred->pid <= 0) {
                 log_warning("Got notification datagram lacking credential information, ignoring.");
                 return 0;
index ec6dad62e83942d592c53c6e572b35cc3478007d..202ac3cda28edf106f52213b8f7c7b93ab658c9f 100644 (file)
@@ -491,8 +491,7 @@ static int stdout_stream_scan(StdoutStream *s, bool force_flush) {
 static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
         uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
         StdoutStream *s = userdata;
-        struct ucred *ucred = NULL;
-        struct cmsghdr *cmsg;
+        struct ucred *ucred;
         struct iovec iovec;
         size_t limit;
         ssize_t l;
@@ -541,25 +540,14 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
                 goto terminate;
         }
 
-        CMSG_FOREACH(cmsg, &msghdr)
-                if (cmsg->cmsg_level == SOL_SOCKET &&
-                    cmsg->cmsg_type == SCM_CREDENTIALS &&
-                    cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
-                        assert(!ucred);
-                        ucred = (struct ucred *)CMSG_DATA(cmsg);
-                        break;
-                }
-
-        /* Invalidate the context if the pid of the sender changed.
-         * This happens when a forked process inherits stdout / stderr
-         * from a parent. In this case getpeercred returns the ucred
-         * of the parent, which can be invalid if the parent has exited
-         * in the meantime.
+        /* Invalidate the context if the pid of the sender changed.  This happens when a forked process
+         * inherits stdout / stderr from a parent. In this case getpeercred returns the ucred of the parent,
+         * which can be invalid if the parent has exited in the meantime.
          */
+        ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
         if (ucred && ucred->pid != s->ucred.pid) {
-                /* force out any previously half-written lines from a
-                 * different process, before we switch to the new ucred
-                 * structure for everything we just added */
+                /* force out any previously half-written lines from a different process, before we switch to
+                 * the new ucred structure for everything we just added */
                 r = stdout_stream_scan(s, true);
                 if (r < 0)
                         goto terminate;
index cc2f1521fff75ff756cb9cd3e2f653fad11f3bf2..c2148596b79ef903437f85cf8cf32a119097b1ad 100644 (file)
@@ -3698,8 +3698,7 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r
                 .msg_control = &control,
                 .msg_controllen = sizeof(control),
         };
-        struct cmsghdr *cmsg;
-        struct ucred *ucred = NULL;
+        struct ucred *ucred;
         ssize_t n;
         pid_t inner_child_pid;
         _cleanup_strv_free_ char **tags = NULL;
@@ -3721,15 +3720,7 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r
 
         cmsg_close_all(&msghdr);
 
-        CMSG_FOREACH(cmsg, &msghdr) {
-                if (cmsg->cmsg_level == SOL_SOCKET &&
-                           cmsg->cmsg_type == SCM_CREDENTIALS &&
-                           cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
-
-                        ucred = (struct ucred*) CMSG_DATA(cmsg);
-                }
-        }
-
+        ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
         if (!ucred || ucred->pid != inner_child_pid) {
                 log_debug("Received notify message without valid credentials. Ignoring.");
                 return 0;
index b7b74260584a71e53ec17ce57b047ced130465e4..7574a510c26f0fdef39c4ceaf23a088cdb3cfea3 100644 (file)
@@ -940,15 +940,12 @@ int ask_password_agent(
                         continue;
                 }
 
-                if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) ||
-                    control.cmsghdr.cmsg_level != SOL_SOCKET ||
-                    control.cmsghdr.cmsg_type != SCM_CREDENTIALS ||
-                    control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) {
+                ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
+                if (!ucred) {
                         log_debug("Received message without credentials. Ignoring.");
                         continue;
                 }
 
-                ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr);
                 if (ucred->uid != 0) {
                         log_debug("Got request from unprivileged user. Ignoring.");
                         continue;
index 4b15159c5b6e8f2511adc9564d1fc1f1cadb1103..cfda47f849b25632b5b6668f13db831209fd1005 100644 (file)
@@ -916,9 +916,8 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat
                         .msg_control = &control,
                         .msg_controllen = sizeof(control),
                 };
-                struct cmsghdr *cmsg;
                 ssize_t size;
-                struct ucred *ucred = NULL;
+                struct ucred *ucred;
                 struct worker *worker;
 
                 size = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT);
@@ -937,12 +936,7 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat
                         continue;
                 }
 
-                CMSG_FOREACH(cmsg, &msghdr)
-                        if (cmsg->cmsg_level == SOL_SOCKET &&
-                            cmsg->cmsg_type == SCM_CREDENTIALS &&
-                            cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
-                                ucred = (struct ucred*) CMSG_DATA(cmsg);
-
+                ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
                 if (!ucred || ucred->pid <= 0) {
                         log_warning("Ignoring worker message without valid PID");
                         continue;