]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] Fix allocation of the control buffer
authorVsevolod Stakhov <vsevolod@rspamd.com>
Sun, 28 Sep 2025 21:06:01 +0000 (22:06 +0100)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Sun, 28 Sep 2025 21:06:01 +0000 (22:06 +0100)
* Refactored rspamd_control_fill_msghdr to accept
  a caller-provided control buffer, fixing the
  lifetime bug where a pointer to a local array
  was stored in msg_control.
* Replaced static buffers with automatic (stack)
  buffers at the exact call sites of sendmsg/recvmsg,
  so PowerPC and similar platforms won’t choke on
  non-constant expressions.

Issue: #5637

src/libserver/rspamd_control.c

index e212f7e91d63f4f59a31aa60f4a5458192a9dcf3..2e1b5a110be1dccd11ade3761a20f36dd4def420 100644 (file)
@@ -373,18 +373,19 @@ void rspamd_pending_control_free(gpointer p)
 static inline void
 rspamd_control_fill_msghdr(struct rspamd_control_command *cmd,
                                                   int attached_fd, struct msghdr *msg,
-                                                  struct iovec *iov)
+                                                  struct iovec *iov,
+                                                  void *control_buf,
+                                                  size_t control_len)
 {
        struct cmsghdr *cmsg;
-       unsigned char fdspace[CMSG_SPACE(sizeof(int))];
 
        memset(msg, 0, sizeof(*msg));
 
        /* Attach fd to the message */
        if (attached_fd != -1) {
-               memset(fdspace, 0, sizeof(fdspace));
-               msg->msg_control = fdspace;
-               msg->msg_controllen = sizeof(fdspace);
+               memset(control_buf, 0, control_len);
+               msg->msg_control = control_buf;
+               msg->msg_controllen = control_len;
                cmsg = CMSG_FIRSTHDR(msg);
                cmsg->cmsg_level = SOL_SOCKET;
                cmsg->cmsg_type = SCM_RIGHTS;
@@ -428,7 +429,9 @@ rspamd_control_stop_pending(struct rspamd_control_reply_elt *elt)
                                struct iovec iov;
 
                                rspamd_main = cur->worker->srv;
-                               rspamd_control_fill_msghdr(&cur->cmd, cur->attached_fd, &msg, &iov);
+                               /* Provide a control buffer with correct lifetime for sendmsg */
+                               unsigned char fdspace[CMSG_SPACE(sizeof(int))];
+                               rspamd_control_fill_msghdr(&cur->cmd, cur->attached_fd, &msg, &iov, fdspace, sizeof(fdspace));
                                ssize_t r = sendmsg(cur->worker->control_pipe[0], &msg, 0);
 
                                if (r == sizeof(cur->cmd)) {
@@ -516,8 +519,9 @@ rspamd_control_broadcast_cmd(struct rspamd_main *rspamd_main,
                        /* We can send command */
                        struct msghdr msg;
                        struct iovec iov;
+                       unsigned char fdspace[CMSG_SPACE(sizeof(int))];
 
-                       rspamd_control_fill_msghdr(cmd, attached_fd, &msg, &iov);
+                       rspamd_control_fill_msghdr(cmd, attached_fd, &msg, &iov, fdspace, sizeof(fdspace));
                        r = sendmsg(wrk->control_pipe[0], &msg, 0);
 
                        if (r == sizeof(*cmd)) {
@@ -768,7 +772,7 @@ rspamd_control_default_worker_handler(EV_P_ ev_io *w, int revents)
        static struct rspamd_control_command cmd;
        static struct msghdr msg;
        static struct iovec iov;
-       static unsigned char fdspace[CMSG_SPACE(sizeof(int))];
+       unsigned char fdspace[CMSG_SPACE(sizeof(int))];
        int rfd = -1;
        gssize r;
 
@@ -987,7 +991,7 @@ rspamd_srv_handler(EV_P_ ev_io *w, int revents)
        struct msghdr msg;
        struct cmsghdr *cmsg;
        static struct iovec iov;
-       static unsigned char fdspace[CMSG_SPACE(sizeof(int))];
+       unsigned char fdspace[CMSG_SPACE(sizeof(int))];
        int *spair, rfd = -1;
        char *nid;
        struct rspamd_control_command wcmd;