From: Lennart Poettering Date: Mon, 7 Aug 2023 13:36:39 +0000 (+0200) Subject: varlink: don't allocate fd control buffer on each read() X-Git-Tag: v255-rc1~798 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3c8680585c698668c4d9774d3801d3446a194113;p=thirdparty%2Fsystemd.git varlink: don't allocate fd control buffer on each read() We'll need this on each read() again, hence let's just allocate this once and then reuse it for subsequent read()s. Follow-up for: #28639 --- diff --git a/src/shared/varlink.c b/src/shared/varlink.c index 9bf9c4b5ac2..97f50a5ed25 100644 --- a/src/shared/varlink.c +++ b/src/shared/varlink.c @@ -133,6 +133,9 @@ struct Varlink { size_t input_buffer_size; size_t input_buffer_unscanned; + void *input_control_buffer; + size_t input_control_buffer_size; + char *output_buffer; /* valid data starts at output_buffer_index, ends at output_buffer_index+output_buffer_size */ size_t output_buffer_index; size_t output_buffer_size; @@ -457,6 +460,9 @@ static void varlink_clear(Varlink *v) { v->input_buffer = mfree(v->input_buffer); v->output_buffer = v->output_buffer_sensitive ? erase_and_free(v->output_buffer) : mfree(v->output_buffer); + v->input_control_buffer = mfree(v->input_control_buffer); + v->input_control_buffer_size = 0; + varlink_clear_current(v); close_many(v->output_fds, v->n_output_fds); @@ -633,7 +639,6 @@ static int varlink_write(Varlink *v) { #define VARLINK_FDS_MAX (16U*1024U) static int varlink_read(Varlink *v) { - _cleanup_free_ struct cmsghdr *cmsg_fds = NULL; struct iovec iov; struct msghdr mh; size_t rs; @@ -687,16 +692,22 @@ static int varlink_read(Varlink *v) { if (v->allow_fd_passing_input) { iov = IOVEC_MAKE(p, rs); + + /* Allocate the fd buffer on the heap, since we need a lot of space potentially */ + if (!v->input_control_buffer) { + v->input_control_buffer_size = CMSG_SPACE(sizeof(int) * VARLINK_FDS_MAX); + v->input_control_buffer = malloc(v->input_control_buffer_size); + if (!v->input_control_buffer) + return -ENOMEM; + } + mh = (struct msghdr) { .msg_iov = &iov, .msg_iovlen = 1, + .msg_control = v->input_control_buffer, + .msg_controllen = v->input_control_buffer_size, }; - mh.msg_controllen = CMSG_SPACE(sizeof(int) * VARLINK_FDS_MAX); - mh.msg_control = cmsg_fds = malloc(mh.msg_controllen); - if (!cmsg_fds) - return -ENOMEM; - n = recvmsg_safe(v->fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); } else { bool prefer_read = v->prefer_read_write;