From: Lennart Poettering Date: Wed, 18 Feb 2015 18:20:47 +0000 (+0100) Subject: shared: introduce cmsg_close_all() call X-Git-Tag: v219.0~637 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=1c8da044469acabcfc479ba3276954da53210830 shared: introduce cmsg_close_all() call 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. --- diff --git a/src/import/importd.c b/src/import/importd.c index 2eef47601..eaf04e6a2 100644 --- a/src/import/importd.c +++ b/src/import/importd.c @@ -518,12 +518,10 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void return -errno; } + cmsg_close_all(&msghdr); + 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))) { diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index 0a61dafc5..44ebc5849 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -475,6 +475,8 @@ int ask_password_agent( goto finish; } + cmsg_close_all(&msghdr); + if (n <= 0) { log_error("Message too short"); continue; diff --git a/src/shared/util.c b/src/shared/util.c index deb983963..dc6528013 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -8110,3 +8110,13 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k 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)); +} diff --git a/src/shared/util.h b/src/shared/util.h index 45cb09443..759d053c2 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -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); + +void cmsg_close_all(struct msghdr *mh); diff --git a/src/shutdownd/shutdownd.c b/src/shutdownd/shutdownd.c index 701882b96..60a646878 100644 --- a/src/shutdownd/shutdownd.c +++ b/src/shutdownd/shutdownd.c @@ -70,12 +70,7 @@ static int read_packet(int fd, union shutdown_buffer *_b) { 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; @@ -83,6 +78,13 @@ static int read_packet(int fd, union shutdown_buffer *_b) { 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 || diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c index 7b5ef6b2a..59a3eceaa 100644 --- a/src/udev/udev-ctrl.c +++ b/src/udev/udev-ctrl.c @@ -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; } + + cmsg_close_all(&smsg); + cmsg = CMSG_FIRSTHDR(&smsg); cred = (struct ucred *) CMSG_DATA(cmsg);