chiark / gitweb /
shared: introduce cmsg_close_all() call
authorLennart Poettering <lennart@poettering.net>
Wed, 18 Feb 2015 18:20:47 +0000 (19:20 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 18 Feb 2015 18:42:24 +0000 (19:42 +0100)
The call iterates through cmsg list and closes all fds passed via
SCM_RIGHTS.

This patch also ensures the call is used wherever appropriate, where we
might get spurious fds sent and we should better close them, then leave
them lying around.

src/import/importd.c
src/shared/ask-password-api.c
src/shared/util.c
src/shared/util.h
src/shutdownd/shutdownd.c
src/udev/udev-ctrl.c

index 2eef476015281677a5f6e83c02d71924ed53f9db..eaf04e6a2b1f7e046270b381829f7fafa3adc8ae 100644 (file)
@@ -518,12 +518,10 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void
                 return -errno;
         }
 
                 return -errno;
         }
 
+        cmsg_close_all(&msghdr);
+
         for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
         for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
-                if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
-                        close_many((int*) CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int));
-                        log_warning("Somebody sent us unexpected fds, ignoring.");
-                        return 0;
-                } else if (cmsg->cmsg_level == SOL_SOCKET &&
+                if (cmsg->cmsg_level == SOL_SOCKET &&
                            cmsg->cmsg_type == SCM_CREDENTIALS &&
                            cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
 
                            cmsg->cmsg_type == SCM_CREDENTIALS &&
                            cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
 
index 0a61dafc59026631532478607488e3736fcd80a1..44ebc584914a6b5092835f0560e8ca09c7e7c299 100644 (file)
@@ -475,6 +475,8 @@ int ask_password_agent(
                         goto finish;
                 }
 
                         goto finish;
                 }
 
+                cmsg_close_all(&msghdr);
+
                 if (n <= 0) {
                         log_error("Message too short");
                         continue;
                 if (n <= 0) {
                         log_error("Message too short");
                         continue;
index deb98396335acbe26ff4f3626c678747537739cd..dc6528013bb0a7fded44e17a9e84e3eb5473b9f8 100644 (file)
@@ -8110,3 +8110,13 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
 
         return -1;
 }
 
         return -1;
 }
+
+void cmsg_close_all(struct msghdr *mh) {
+        struct cmsghdr *cmsg;
+
+        assert(mh);
+
+        for (cmsg = CMSG_FIRSTHDR(mh); cmsg; cmsg = CMSG_NXTHDR(mh, cmsg))
+                if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
+                        close_many((int*) CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int));
+}
index 45cb09443d62edd896c2c106e4ba6280f9b2ecf9..759d053c25c7d9a69cb32fe48c5a5e0194006354 100644 (file)
@@ -1080,3 +1080,5 @@ void sigkill_wait(pid_t *pid);
 #define _cleanup_sigkill_wait_ _cleanup_(sigkill_wait)
 
 int syslog_parse_priority(const char **p, int *priority, bool with_facility);
 #define _cleanup_sigkill_wait_ _cleanup_(sigkill_wait)
 
 int syslog_parse_priority(const char **p, int *priority, bool with_facility);
+
+void cmsg_close_all(struct msghdr *mh);
index 701882b96d58da442077c825babb3d63e1c031ad..60a646878e501725459aa1fbe971dba37f9b3084 100644 (file)
@@ -70,12 +70,7 @@ static int read_packet(int fd, union shutdown_buffer *_b) {
         assert(_b);
 
         n = recvmsg(fd, &msghdr, MSG_DONTWAIT);
         assert(_b);
 
         n = recvmsg(fd, &msghdr, MSG_DONTWAIT);
-        if (n <= 0) {
-                if (n == 0) {
-                        log_error("Short read");
-                        return -EIO;
-                }
-
+        if (n < 0) {
                 if (errno == EAGAIN || errno == EINTR)
                         return 0;
 
                 if (errno == EAGAIN || errno == EINTR)
                         return 0;
 
@@ -83,6 +78,13 @@ static int read_packet(int fd, union shutdown_buffer *_b) {
                 return -errno;
         }
 
                 return -errno;
         }
 
+        cmsg_close_all(&msghdr);
+
+        if (n == 0) {
+                log_error("Short read");
+                return -EIO;
+        }
+
         if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) ||
             control.cmsghdr.cmsg_level != SOL_SOCKET ||
             control.cmsghdr.cmsg_type != SCM_CREDENTIALS ||
         if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) ||
             control.cmsghdr.cmsg_level != SOL_SOCKET ||
             control.cmsghdr.cmsg_type != SCM_CREDENTIALS ||
index 7b5ef6b2a8e6fbfcd71659722cc8aeeeb6ac6a4b..59a3eceaadea7cc2959f4c8a52b7d87b3bec774e 100644 (file)
@@ -377,6 +377,9 @@ struct udev_ctrl_msg *udev_ctrl_receive_msg(struct udev_ctrl_connection *conn) {
                 log_error_errno(errno, "unable to receive ctrl message: %m");
                 goto err;
         }
                 log_error_errno(errno, "unable to receive ctrl message: %m");
                 goto err;
         }
+
+        cmsg_close_all(&smsg);
+
         cmsg = CMSG_FIRSTHDR(&smsg);
         cred = (struct ucred *) CMSG_DATA(cmsg);
 
         cmsg = CMSG_FIRSTHDR(&smsg);
         cred = (struct ucred *) CMSG_DATA(cmsg);