]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tree-wide: make sure our control buffers are properly aligned 15623/head
authorLennart Poettering <lennart@poettering.net>
Fri, 24 Apr 2020 21:54:25 +0000 (23:54 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 7 May 2020 12:39:44 +0000 (14:39 +0200)
We always need to make them unions with a "struct cmsghdr" in them, so
that things properly aligned. Otherwise we might end up at an unaligned
address and the counting goes all wrong, possibly making the kernel
refuse our buffers.

Also, let's make sure we initialize the control buffers to zero when
sending, but leave them uninitialized when reading.

Both the alignment and the initialization thing is mentioned in the
cmsg(3) man page.

22 files changed:
src/basic/socket-util.c
src/basic/socket-util.h
src/core/manager.c
src/coredump/coredump.c
src/home/homed-manager.c
src/import/importd.c
src/journal/journald-server.c
src/journal/journald-stream.c
src/journal/journald-syslog.c
src/libsystemd-network/icmp6-util.c
src/libsystemd-network/sd-dhcp-client.c
src/libsystemd-network/sd-dhcp-server.c
src/libsystemd/sd-bus/bus-socket.c
src/libsystemd/sd-device/device-monitor.c
src/nspawn/nspawn.c
src/portable/portable.c
src/resolve/resolved-dns-stream.c
src/resolve/resolved-manager.c
src/shared/ask-password-api.c
src/timesync/timesyncd-manager.c
src/udev/udev-ctrl.c
src/udev/udevd.c

index a23dd6cbed5e4599f09a946fba84685b5490ec98..0be098df2ea1e411310c3dec500ded5bd0051003 100644 (file)
@@ -818,10 +818,7 @@ ssize_t send_one_fd_iov_sa(
                 const struct sockaddr *sa, socklen_t len,
                 int flags) {
 
-        union {
-                struct cmsghdr cmsghdr;
-                uint8_t buf[CMSG_SPACE(sizeof(int))];
-        } control = {};
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int))) control = {};
         struct msghdr mh = {
                 .msg_name = (struct sockaddr*) sa,
                 .msg_namelen = len,
@@ -875,10 +872,7 @@ ssize_t receive_one_fd_iov(
                 int flags,
                 int *ret_fd) {
 
-        union {
-                struct cmsghdr cmsghdr;
-                uint8_t buf[CMSG_SPACE(sizeof(int))];
-        } control = {};
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int))) control;
         struct msghdr mh = {
                 .msg_control = &control,
                 .msg_controllen = sizeof(control),
index fba4efef814ea5289e2e4644ae2877761073ee5b..6f366c042998184d190f0bd8222a321c388b71e0 100644 (file)
@@ -166,6 +166,17 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng
                 (ctype*) (_found ? CMSG_DATA(_found) : NULL);         \
         })
 
+/* Resolves to a type that can carry cmsghdr structures. Make sure things are properly aligned, i.e. the type
+ * itself is placed properly in memory and the size is also aligned to what's appropriate for "cmsghdr"
+ * structures. */
+#define CMSG_BUFFER_TYPE(size)                                          \
+        union {                                                         \
+                struct cmsghdr cmsghdr;                                 \
+                uint8_t buf[size];                                      \
+                uint8_t align_check[(size) >= CMSG_SPACE(0) &&          \
+                                    (size) == CMSG_ALIGN(size) ? 1 : -1]; \
+        }
+
 /*
  * 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 7c207bed6e70c442f810c89f5706ac2834c8f630..09dc92d599a4c2ae1900623a8be36bf651f0ddc8 100644 (file)
@@ -2349,11 +2349,8 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
                 .iov_base = buf,
                 .iov_len = sizeof(buf)-1,
         };
-        union {
-                struct cmsghdr cmsghdr;
-                uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
-                            CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)];
-        } control = {};
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred)) +
+                         CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)) control;
         struct msghdr msghdr = {
                 .msg_iov = &iovec,
                 .msg_iovlen = 1,
index ff4238c91d7e86b1530ade5679e7f8cf82f49451..42231dbd6b679d05205849690ee71491051bc3cc 100644 (file)
@@ -884,10 +884,7 @@ static int process_socket(int fd) {
         log_debug("Processing coredump received on stdin...");
 
         for (;;) {
-                union {
-                        struct cmsghdr cmsghdr;
-                        uint8_t buf[CMSG_SPACE(sizeof(int))];
-                } control = {};
+                CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int))) control;
                 struct msghdr mh = {
                         .msg_control = &control,
                         .msg_controllen = sizeof(control),
index 8ea93120d07529b60ea790fa7596db965b655194..70673fc84d6e1fcd39a97809e2879ff4b038abfc 100644 (file)
@@ -946,10 +946,7 @@ static ssize_t read_datagram(int fd, struct ucred *ret_sender, void **ret) {
                 return -ENOMEM;
 
         if (ret_sender) {
-                union {
-                        struct cmsghdr cmsghdr;
-                        uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
-                } control;
+                CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
                 bool found_ucred = false;
                 struct cmsghdr *cmsg;
                 struct msghdr mh;
index 9408edece10ca8b389b4673b846005c78366ff8f..d799a10f94b24d3f931ab7ae19ed9e1b0fe7332e 100644 (file)
@@ -550,11 +550,8 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void
                 .iov_base = buf,
                 .iov_len = sizeof(buf)-1,
         };
-        union {
-                struct cmsghdr cmsghdr;
-                uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
-                            CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)];
-        } control = {};
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred)) +
+                         CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)) control;
         struct msghdr msghdr = {
                 .msg_iov = &iovec,
                 .msg_iovlen = 1,
index 981a569453a516a87d6e5ae5e9d8473a055a100e..9efa65a29427d88882b567411edda70218431e50 100644 (file)
@@ -1268,21 +1268,14 @@ int server_process_datagram(
         int *fds = NULL, v = 0;
         size_t n_fds = 0;
 
-        union {
-                struct cmsghdr cmsghdr;
-
-                /* We use NAME_MAX space for the SELinux label
-                 * here. The kernel currently enforces no
-                 * limit, but according to suggestions from
-                 * the SELinux people this will change and it
-                 * will probably be identical to NAME_MAX. For
-                 * now we use that, but this should be updated
-                 * one day when the final limit is known. */
-                uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
-                            CMSG_SPACE(sizeof(struct timeval)) +
-                            CMSG_SPACE(sizeof(int)) + /* fd */
-                            CMSG_SPACE(NAME_MAX)]; /* selinux label */
-        } control = {};
+        /* We use NAME_MAX space for the SELinux label here. The kernel currently enforces no limit, but
+         * according to suggestions from the SELinux people this will change and it will probably be
+         * identical to NAME_MAX. For now we use that, but this should be updated one day when the final
+         * limit is known. */
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred)) +
+                         CMSG_SPACE(sizeof(struct timeval)) +
+                         CMSG_SPACE(sizeof(int)) + /* fd */
+                         CMSG_SPACE(NAME_MAX) /* selinux label */) control;
 
         union sockaddr_union sa = {};
 
index 202ac3cda28edf106f52213b8f7c7b93ab658c9f..4dadbd62bec3201d9be4781470e893bf2c753393 100644 (file)
@@ -489,7 +489,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))];
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
         StdoutStream *s = userdata;
         struct ucred *ucred;
         struct iovec iovec;
@@ -500,8 +500,8 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
         struct msghdr msghdr = {
                 .msg_iov = &iovec,
                 .msg_iovlen = 1,
-                .msg_control = buf,
-                .msg_controllen = sizeof(buf),
+                .msg_control = &control,
+                .msg_controllen = sizeof(control),
         };
 
         assert(s);
index 1325b563854f6f5da2f9b41def2dc3abdb7712c6..46013c38784d2f1c88b7278bac8f70839f702114 100644 (file)
@@ -39,10 +39,7 @@ static void forward_syslog_iovec(
                 .msg_iovlen = n_iovec,
         };
         struct cmsghdr *cmsg;
-        union {
-                struct cmsghdr cmsghdr;
-                uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
-        } control;
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
         const char *j;
         int r;
 
index 1a51c22a8d09c5943163ad9fdbd0e2603a6d0c10..bdd94867ac33b88c79e0622eaefa151605e26021 100644 (file)
@@ -147,11 +147,9 @@ int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
 
 int icmp6_receive(int fd, void *buffer, size_t size, struct in6_addr *dst,
                   triple_timestamp *timestamp) {
-        union {
-                struct cmsghdr cmsghdr;
-                uint8_t buf[CMSG_SPACE(sizeof(int)) + /* ttl */
-                            CMSG_SPACE(sizeof(struct timeval))];
-        } control = {};
+
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int)) + /* ttl */
+                         CMSG_SPACE(sizeof(struct timeval))) control;
         struct iovec iov = {};
         union sockaddr_union sa = {};
         struct msghdr msg = {
index 47f60d4a2a3ab655757cd6b6387357c88b2eeb23..ee0e63e113c161c488a938347aa47ee90f00daf5 100644 (file)
@@ -1899,13 +1899,13 @@ static int client_receive_message_raw(
 
         sd_dhcp_client *client = userdata;
         _cleanup_free_ DHCPPacket *packet = NULL;
-        uint8_t cmsgbuf[CMSG_SPACE(sizeof(struct tpacket_auxdata))];
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct tpacket_auxdata))) control;
         struct iovec iov = {};
         struct msghdr msg = {
                 .msg_iov = &iov,
                 .msg_iovlen = 1,
-                .msg_control = cmsgbuf,
-                .msg_controllen = sizeof(cmsgbuf),
+                .msg_control = &control,
+                .msg_controllen = sizeof(control),
         };
         struct cmsghdr *cmsg;
         bool checksum = true;
index 59792af68630a50886af97043730a2f2e8de1e4b..14f2bcb4fb8066699fd9a573ecefa04fce52abca 100644 (file)
@@ -267,14 +267,14 @@ static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination,
                 .iov_base = message,
                 .iov_len = len,
         };
-        uint8_t cmsgbuf[CMSG_SPACE(sizeof(struct in_pktinfo))] = {};
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct in_pktinfo))) control = {};
         struct msghdr msg = {
                 .msg_name = &dest,
                 .msg_namelen = sizeof(dest.in),
                 .msg_iov = &iov,
                 .msg_iovlen = 1,
-                .msg_control = cmsgbuf,
-                .msg_controllen = sizeof(cmsgbuf),
+                .msg_control = &control,
+                .msg_controllen = sizeof(control),
         };
         struct cmsghdr *cmsg;
         struct in_pktinfo *pktinfo;
@@ -970,14 +970,14 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
 static int server_receive_message(sd_event_source *s, int fd,
                                   uint32_t revents, void *userdata) {
         _cleanup_free_ DHCPMessage *message = NULL;
-        uint8_t cmsgbuf[CMSG_SPACE(sizeof(struct in_pktinfo))];
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct in_pktinfo))) control;
         sd_dhcp_server *server = userdata;
         struct iovec iov = {};
         struct msghdr msg = {
                 .msg_iov = &iov,
                 .msg_iovlen = 1,
-                .msg_control = cmsgbuf,
-                .msg_controllen = sizeof(cmsgbuf),
+                .msg_control = &control,
+                .msg_controllen = sizeof(control),
         };
         struct cmsghdr *cmsg;
         ssize_t buflen, len;
index e336dbb62ed94c7fc864213500d638c8756ad2e8..acc313d164bf59fc149e757b79ef1b7e81a6eb49 100644 (file)
@@ -518,10 +518,7 @@ static int bus_socket_read_auth(sd_bus *b) {
         ssize_t k;
         int r;
         void *p;
-        union {
-                struct cmsghdr cmsghdr;
-                uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)];
-        } control;
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)) control;
         bool handle_cmsg = false;
 
         assert(b);
@@ -1169,10 +1166,7 @@ int bus_socket_read_message(sd_bus *bus) {
         size_t need;
         int r;
         void *b;
-        union {
-                struct cmsghdr cmsghdr;
-                uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)];
-        } control;
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)) control;
         bool handle_cmsg = false;
 
         assert(bus);
index 42753abe0834aa3dbe8744c0694461de09dbe1f3..20a422c77cf347add270c7d417b486ab2ee62c70 100644 (file)
@@ -361,13 +361,13 @@ int device_monitor_receive_device(sd_device_monitor *m, sd_device **ret) {
                 .iov_base = &buf,
                 .iov_len = sizeof(buf)
         };
-        char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
         union sockaddr_union snl;
         struct msghdr smsg = {
                 .msg_iov = &iov,
                 .msg_iovlen = 1,
-                .msg_control = cred_msg,
-                .msg_controllen = sizeof(cred_msg),
+                .msg_control = &control,
+                .msg_controllen = sizeof(control),
                 .msg_name = &snl,
                 .msg_namelen = sizeof(snl),
         };
index 43c6b6845ed1960bef344941780866edf8ad8b37..8e8881749aa54f56cf21936c8767a80556b65f9b 100644 (file)
@@ -3687,11 +3687,8 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r
                 .iov_base = buf,
                 .iov_len = sizeof(buf)-1,
         };
-        union {
-                struct cmsghdr cmsghdr;
-                uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
-                            CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)];
-        } control = {};
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred)) +
+                         CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)) control;
         struct msghdr msghdr = {
                 .msg_iov = &iovec,
                 .msg_iovlen = 1,
index 4a881460dbbca4f06c954c087f22c642a44635c8..f47a3329fb9188043d6c2d123e408f920b37f88a 100644 (file)
@@ -127,10 +127,7 @@ static int send_item(
                 const char *name,
                 int fd) {
 
-        union {
-                struct cmsghdr cmsghdr;
-                uint8_t buf[CMSG_SPACE(sizeof(int))];
-        } control = {};
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int))) control = {};
         struct iovec iovec;
         struct msghdr mh = {
                 .msg_control = &control,
@@ -168,10 +165,7 @@ static int recv_item(
                 char **ret_name,
                 int *ret_fd) {
 
-        union {
-                struct cmsghdr cmsghdr;
-                uint8_t buf[CMSG_SPACE(sizeof(int))];
-        } control = {};
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int))) control;
         char buffer[PATH_MAX+2];
         struct iovec iov = IOVEC_INIT(buffer, sizeof(buffer)-1);
         struct msghdr mh = {
index 9c47cd60e423246e81f3a1d49ad46d43edd7ed3b..bbaffc165ac3b9eb26818095f1e8c24427400129 100644 (file)
@@ -87,11 +87,8 @@ static int dns_stream_complete(DnsStream *s, int error) {
 }
 
 static int dns_stream_identify(DnsStream *s) {
-        union {
-                struct cmsghdr header; /* For alignment */
-                uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
-                               + EXTRA_CMSG_SPACE /* kernel appears to require extra space */];
-        } control;
+        CMSG_BUFFER_TYPE(CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
+                         + EXTRA_CMSG_SPACE /* kernel appears to require extra space */) control;
         struct msghdr mh = {};
         struct cmsghdr *cmsg;
         socklen_t sl;
index 69630cf49d31c3bd1be3c0669eb8dedf2e9becc4..1da590b68acc418056c3fdc229e273b14b785f50 100644 (file)
@@ -741,12 +741,9 @@ Manager *manager_free(Manager *m) {
 
 int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
-        union {
-                struct cmsghdr header; /* For alignment */
-                uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
-                               + CMSG_SPACE(int) /* ttl/hoplimit */
-                               + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */];
-        } control;
+        CMSG_BUFFER_TYPE(CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
+                         + CMSG_SPACE(int) /* ttl/hoplimit */
+                         + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */) control;
         union sockaddr_union sa;
         struct iovec iov;
         struct msghdr mh = {
@@ -930,10 +927,8 @@ static int manager_ipv4_send(
                 uint16_t port,
                 const struct in_addr *source,
                 DnsPacket *p) {
-        union {
-                struct cmsghdr header; /* For alignment */
-                uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
-        } control = {};
+
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct in_pktinfo))) control = {};
         union sockaddr_union sa;
         struct iovec iov;
         struct msghdr mh = {
@@ -988,10 +983,7 @@ static int manager_ipv6_send(
                 const struct in6_addr *source,
                 DnsPacket *p) {
 
-        union {
-                struct cmsghdr header; /* For alignment */
-                uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
-        } control = {};
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct in6_pktinfo))) control = {};
         union sockaddr_union sa;
         struct iovec iov;
         struct msghdr mh = {
index e690b0fa6ea4bc4f716ec3d21a7e0f71df38944b..4c5781a11ad5830ac4c81760ce5225e0bc777b47 100644 (file)
@@ -859,13 +859,10 @@ int ask_password_agent(
         pollfd[FD_INOTIFY].events = POLLIN;
 
         for (;;) {
+                CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
                 char passphrase[LINE_MAX+1];
                 struct iovec iovec;
                 struct ucred *ucred;
-                union {
-                        struct cmsghdr cmsghdr;
-                        uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
-                } control;
                 ssize_t n;
                 int k;
                 usec_t t;
@@ -917,7 +914,6 @@ int ask_password_agent(
 
                 iovec = IOVEC_MAKE(passphrase, sizeof(passphrase));
 
-                zero(control);
                 struct msghdr msghdr = {
                         .msg_iov = &iovec,
                         .msg_iovlen = 1,
index 2980f79b16f8388b91c5ad22ffb59a01f076c161..dadf213a809ff741fe18eb05031c09d55be3ed83 100644 (file)
@@ -407,10 +407,7 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re
                 .iov_base = &ntpmsg,
                 .iov_len = sizeof(ntpmsg),
         };
-        union {
-                struct cmsghdr cmsghdr;
-                uint8_t buf[CMSG_SPACE(sizeof(struct timeval))];
-        } control;
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct timeval))) control;
         union sockaddr_union server_addr;
         struct msghdr msghdr = {
                 .msg_iov = &iov,
index d067279f3e1aea02c555a5a41a05af9607d18fcf..1e51f22e26035c41b0873e9a314c1488d430f004 100644 (file)
@@ -189,12 +189,12 @@ static int udev_ctrl_connection_event_handler(sd_event_source *s, int fd, uint32
         _cleanup_(udev_ctrl_disconnect_and_listen_againp) struct udev_ctrl *uctrl = NULL;
         struct udev_ctrl_msg_wire msg_wire;
         struct iovec iov = IOVEC_MAKE(&msg_wire, sizeof(struct udev_ctrl_msg_wire));
-        char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
         struct msghdr smsg = {
                 .msg_iov = &iov,
                 .msg_iovlen = 1,
-                .msg_control = cred_msg,
-                .msg_controllen = sizeof(cred_msg),
+                .msg_control = &control,
+                .msg_controllen = sizeof(control),
         };
         struct cmsghdr *cmsg;
         struct ucred *cred;
index cfda47f849b25632b5b6668f13db831209fd1005..d3f9d532e18ff0335ce980ae57178161ea145184 100644 (file)
@@ -906,10 +906,7 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat
                         .iov_base = &msg,
                         .iov_len = sizeof(msg),
                 };
-                union {
-                        struct cmsghdr cmsghdr;
-                        uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
-                } control = {};
+                CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
                 struct msghdr msghdr = {
                         .msg_iov = &iovec,
                         .msg_iovlen = 1,