From: Lennart Poettering Date: Tue, 7 Jul 2026 09:13:38 +0000 (+0200) Subject: sd-varlink: move varlink_handle_upgrade_fds() before sd_varlink_process() X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f194afa164ad5d1eeec0cb4d7a426dce48dad6b7;p=thirdparty%2Fsystemd.git sd-varlink: move varlink_handle_upgrade_fds() before sd_varlink_process() This is a simple move, in preparation for using this as part of the sd_varlink_process() callchain. --- diff --git a/src/libsystemd/sd-varlink/sd-varlink.c b/src/libsystemd/sd-varlink/sd-varlink.c index ea616a6fd3a..dd1e01c5ba8 100644 --- a/src/libsystemd/sd-varlink/sd-varlink.c +++ b/src/libsystemd/sd-varlink/sd-varlink.c @@ -1427,6 +1427,53 @@ fail: return r; } +static int varlink_handle_upgrade_fds(sd_varlink *v, int *ret_input_fd, int *ret_output_fd) { + int r; + + assert(v); + assert(ret_input_fd || ret_output_fd); + + /* Ensure no post-upgrade data was consumed into our input buffer (we ensure this via MSG_PEEK or + * byte-to-byte) and refuse the upgrade rather than silently losing the data. */ + if (json_stream_has_buffered_input(&v->stream)) + return varlink_log_errno(v, SYNTHETIC_ERRNO(EPROTO), + "Unexpected buffered data during protocol upgrade, refusing."); + + _cleanup_close_ int input_fd = TAKE_FD(v->stream.input_fd), + output_fd = TAKE_FD(v->stream.output_fd); + + /* Pass the connection fds to the caller, it owns them now. Reset to blocking mode + * since callers of the upgraded protocol will generally expect normal blocking + * semantics. For bidirectional sockets (input_fd == output_fd), dup the fd so that + * callers always get two independent fds they can close separately. */ + if (input_fd == output_fd) { + output_fd = fcntl(input_fd, F_DUPFD_CLOEXEC, 3); + if (output_fd < 0) + return varlink_log_errno(v, errno, "Failed to dup upgraded connection fd: %m"); + } else { + r = fd_nonblock(output_fd, false); + if (r < 0) + return varlink_log_errno(v, r, "Failed to set output fd to blocking mode: %m"); + } + + r = fd_nonblock(input_fd, false); + if (r < 0) + return varlink_log_errno(v, r, "Failed to set input fd to blocking mode: %m"); + + /* Hand out requested fds, shut down unwanted directions. */ + if (ret_input_fd) + *ret_input_fd = TAKE_FD(input_fd); + else + (void) shutdown(input_fd, SHUT_RD); + + if (ret_output_fd) + *ret_output_fd = TAKE_FD(output_fd); + else + (void) shutdown(output_fd, SHUT_WR); + + return 0; +} + _public_ int sd_varlink_process(sd_varlink *v) { int r; @@ -2011,53 +2058,6 @@ _public_ int sd_varlink_call( return sd_varlink_call_full(v, method, parameters, ret_parameters, ret_error_id, NULL); } -static int varlink_handle_upgrade_fds(sd_varlink *v, int *ret_input_fd, int *ret_output_fd) { - int r; - - assert(v); - assert(ret_input_fd || ret_output_fd); - - /* Ensure no post-upgrade data was consumed into our input buffer (we ensure this via MSG_PEEK or - * byte-to-byte) and refuse the upgrade rather than silently losing the data. */ - if (json_stream_has_buffered_input(&v->stream)) - return varlink_log_errno(v, SYNTHETIC_ERRNO(EPROTO), - "Unexpected buffered data during protocol upgrade, refusing."); - - _cleanup_close_ int input_fd = TAKE_FD(v->stream.input_fd), - output_fd = TAKE_FD(v->stream.output_fd); - - /* Pass the connection fds to the caller, it owns them now. Reset to blocking mode - * since callers of the upgraded protocol will generally expect normal blocking - * semantics. For bidirectional sockets (input_fd == output_fd), dup the fd so that - * callers always get two independent fds they can close separately. */ - if (input_fd == output_fd) { - output_fd = fcntl(input_fd, F_DUPFD_CLOEXEC, 3); - if (output_fd < 0) - return varlink_log_errno(v, errno, "Failed to dup upgraded connection fd: %m"); - } else { - r = fd_nonblock(output_fd, false); - if (r < 0) - return varlink_log_errno(v, r, "Failed to set output fd to blocking mode: %m"); - } - - r = fd_nonblock(input_fd, false); - if (r < 0) - return varlink_log_errno(v, r, "Failed to set input fd to blocking mode: %m"); - - /* Hand out requested fds, shut down unwanted directions. */ - if (ret_input_fd) - *ret_input_fd = TAKE_FD(input_fd); - else - (void) shutdown(input_fd, SHUT_RD); - - if (ret_output_fd) - *ret_output_fd = TAKE_FD(output_fd); - else - (void) shutdown(output_fd, SHUT_WR); - - return 0; -} - _public_ int sd_varlink_call_and_upgrade( sd_varlink *v, const char *method,