diff --git a/backport-Remove-status-bits-from-OpenSSL-3-version-check.patch b/backport-Remove-status-bits-from-OpenSSL-3-version-check.patch new file mode 100644 index 0000000000000000000000000000000000000000..11201940f83753ed29ffd86ea8f1046e0a66aef7 --- /dev/null +++ b/backport-Remove-status-bits-from-OpenSSL-3-version-check.patch @@ -0,0 +1,59 @@ +From e914e61eb88e22e5b725c399698256c54589ca32 Mon Sep 17 00:00:00 2001 +From: Darren Tucker +Date: Thu, 25 Sep 2025 17:50:07 +1000 +Subject: Remove status bits from OpenSSL >=3 version check. + +OpenSSL traditionally did not guarantee ABI compatibility across release +(and development) versions. Because of this, OpenSSH checked the lower 4 +"status" bits returned by OpenSSL_version_num(), which were originally +set to 0 for development versions and 0xf for release versions and, if +they did not match, would report the discrepancy and exit. + +OpenSSL (unintentionally) changed these bits in the 3.0.0 and subsequent +3.x releases, setting them to zero in the release versions (which happened +to also match the documentation), then changed them back in the 3.5.3 +release. If OpenSSL was upgraded to (or from) this version without +recompiling OpenSSH, it would cause OpenSSH flag it as potentially +incompatible and refuse to use it. Ultimately OpenSSL rolled this +back, but the check now has no value so is being removed for OpenSSL +versions >=3. + +bz#3865 and https://github.com/openssl/openssl/issues/28575, ok djm@ + +Conflict:NA +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=e914e61eb88e22e5b725c399698256c54589ca32 +--- + openbsd-compat/openssl-compat.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/openbsd-compat/openssl-compat.c b/openbsd-compat/openssl-compat.c +index 14865077e..48938920c 100644 +--- a/openbsd-compat/openssl-compat.c ++++ b/openbsd-compat/openssl-compat.c +@@ -32,7 +32,8 @@ + #include "openssl-compat.h" + + /* +- * OpenSSL version numbers: MNNFFPPS: major minor fix patch status ++ * OpenSSL version numbers: MNNFFPPS: major minor fix patch status. ++ * See the OpenSSL_version_num(3ssl) man page. + * Versions >=3 require only major versions to match. + * For versions <3, we accept compatible fix versions (so we allow 1.0.1 + * to work with 1.0.0). Going backwards is only allowed within a patch series. +@@ -49,10 +50,10 @@ ssh_compatible_openssl(long headerver, long libver) + return 1; + + /* +- * For versions >= 3.0, only the major and status must match. ++ * For versions >= 3.0, only the major must match. + */ +- if (headerver >= 0x3000000f) { +- mask = 0xf000000fL; /* major,status */ ++ if (headerver >= 0x30000000) { ++ mask = 0xf0000000L; /* major only */ + return (headerver & mask) == (libver & mask); + } + +-- +cgit v1.2.3 + diff --git a/backport-ensure-struct-passwd-fields-are-non-NULL-in-pwcopy.patch b/backport-ensure-struct-passwd-fields-are-non-NULL-in-pwcopy.patch new file mode 100644 index 0000000000000000000000000000000000000000..ff912a907b7010c6d061309cb3bc5eefdc3f8806 --- /dev/null +++ b/backport-ensure-struct-passwd-fields-are-non-NULL-in-pwcopy.patch @@ -0,0 +1,42 @@ +From d343df4019b4369ce7f87e9bf6bbc80b81cd263d Mon Sep 17 00:00:00 2001 +From: zhangjun +Date: Fri, 22 Aug 2025 16:49:07 +0800 +Subject: ensure struct passwd fields are non-NULL in pwcopy + +Android libc can return NULL pw_gecos, for example. +Conflict:NA +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=d343df4019b4369ce7f87e9bf6bbc80b81cd263d +--- + misc.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/misc.c b/misc.c +index 6226030..b3cc986 100644 +--- a/misc.c ++++ b/misc.c +@@ -488,7 +488,7 @@ pwcopy(struct passwd *pw) + copy->pw_name = xstrdup(pw->pw_name); + copy->pw_passwd = xstrdup(pw->pw_passwd == NULL ? "*" : pw->pw_passwd); + #ifdef HAVE_STRUCT_PASSWD_PW_GECOS +- copy->pw_gecos = xstrdup(pw->pw_gecos); ++ copy->pw_gecos = xstrdup(pw->pw_gecos == NULL ? "" : pw->pw_gecos); + #endif + copy->pw_uid = pw->pw_uid; + copy->pw_gid = pw->pw_gid; +@@ -499,10 +499,10 @@ pwcopy(struct passwd *pw) + copy->pw_change = pw->pw_change; + #endif + #ifdef HAVE_STRUCT_PASSWD_PW_CLASS +- copy->pw_class = xstrdup(pw->pw_class); ++ copy->pw_class = xstrdup(pw->pw_class == NULL ? "" : pw->pw_class); + #endif +- copy->pw_dir = xstrdup(pw->pw_dir); +- copy->pw_shell = xstrdup(pw->pw_shell); ++ copy->pw_dir = xstrdup(pw->pw_dir == NULL ? "" : pw->pw_dir); ++ copy->pw_shell = xstrdup(pw->pw_shell == NULL ? "" : pw->pw_shell); + return copy; + } + +-- +2.43.0 + diff --git a/backport-upstream-Activate-UnusedConnectionTimeout-only-after-last-channel.patch b/backport-upstream-Activate-UnusedConnectionTimeout-only-after-last-channel.patch new file mode 100644 index 0000000000000000000000000000000000000000..5e0713ff5a8653942248cc7e0fa9982e6dc01bc7 --- /dev/null +++ b/backport-upstream-Activate-UnusedConnectionTimeout-only-after-last-channel.patch @@ -0,0 +1,46 @@ +From 4f3e65bda22b65dc5fff82df1e97af07456fed42 Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Thu, 30 Oct 2025 03:19:54 +0000 +Subject: upstream: Activate UnusedConnectionTimeout only after last channel + +has closed. Previously UnusedConnectionTimeout could fire early after a +ChannelTimeout. + +This was not a problem for the OpenSSH client because it terminates +once all channels have closed but could cause problems for other +clients (e.g. API clients) that do things differently. + +bz3827; ok dtucker + +OpenBSD-Commit-ID: ff2e4607cbd4e600de3c8a5ece3b0e4bb641ed8f +Conflict:NA +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=4f3e65bda22b65dc5fff82df1e97af07456fed42 +--- + serverloop.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/serverloop.c b/serverloop.c +index b74484f..996d1de 100644 +--- a/serverloop.c ++++ b/serverloop.c +@@ -194,12 +194,15 @@ wait_until_can_do_something(struct ssh *ssh, + * start the clock to terminate the connection. + */ + if (options.unused_connection_timeout != 0) { +- if (channel_still_open(ssh) || unused_connection_expiry == 0) { ++ if (channel_still_open(ssh)) ++ unused_connection_expiry = 0; ++ else if (unused_connection_expiry == 0) { + unused_connection_expiry = now + + options.unused_connection_timeout; + } +- ptimeout_deadline_monotime(&timeout, unused_connection_expiry); + } ++ if (unused_connection_expiry != 0) ++ ptimeout_deadline_monotime(&timeout, unused_connection_expiry); + + /* + * if using client_alive, set the max timeout accordingly, +-- +2.43.0 + diff --git a/backport-upstream-When-tab-completing-a-filename-ensure-that-the-completed.patch b/backport-upstream-When-tab-completing-a-filename-ensure-that-the-completed.patch new file mode 100644 index 0000000000000000000000000000000000000000..da62e80bcf89833c092a47ef1b89422dadf62734 --- /dev/null +++ b/backport-upstream-When-tab-completing-a-filename-ensure-that-the-completed.patch @@ -0,0 +1,96 @@ +From 0f3b8fd68a29766697d7a709bae8b0a61da6cff2 Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Wed, 8 Oct 2025 21:48:40 +0000 +Subject: upstream: When tab-completing a filename, ensure that the completed + +string does not end up mid-way through a multibyte character, as this will +cause a fatal() later on. + +based on GHPR#587 from @TaoistBrickscarrier; feedback tb@ kevlo@ +ok dtucker@ + +OpenBSD-Commit-ID: efb977164b4e20d61204a66201a7592ba8291362 +Conflict:NA +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=0f3b8fd68a29766697d7a709bae8b0a61da6cff2 +--- + sftp.c | 52 ++++++++++++++++++++++++++++++++++------------------ + 1 file changed, 34 insertions(+), 18 deletions(-) + +diff --git a/sftp.c b/sftp.c +index cab44a9..93868e7 100644 +--- a/sftp.c ++++ b/sftp.c +@@ -1869,29 +1869,44 @@ complete_display(char **list, u_int len) + static char * + complete_ambiguous(const char *word, char **list, size_t count) + { ++ size_t i, j, matchlen; ++ char *tmp; ++ int len; ++ + if (word == NULL) + return NULL; + +- if (count > 0) { +- u_int y, matchlen = strlen(list[0]); +- +- /* Find length of common stem */ +- for (y = 1; list[y]; y++) { +- u_int x; +- +- for (x = 0; x < matchlen; x++) +- if (list[0][x] != list[y][x]) +- break; +- +- matchlen = x; +- } ++ if (count == 0) ++ return xstrdup(word); /* no options to complete */ + +- if (matchlen > strlen(word)) { +- char *tmp = xstrdup(list[0]); ++ /* Find length of common stem across list */ ++ matchlen = strlen(list[0]); ++ for (i = 1; i < count && list[i] != NULL; i++) { ++ for (j = 0; j < matchlen; j++) ++ if (list[0][j] != list[i][j]) ++ break; ++ matchlen = j; ++ } + +- tmp[matchlen] = '\0'; +- return tmp; +- } ++ /* ++ * Now check that the common stem doesn't finish in the middle of ++ * a multibyte character. ++ */ ++ mblen(NULL, 0); ++ for (i = 0; i < matchlen;) { ++ len = mblen(list[0] + i, matchlen - i); ++ if (len <= 0 || i + (size_t)len > matchlen) ++ break; ++ i += (size_t)len; ++ } ++ /* If so, truncate */ ++ if (i < matchlen) ++ matchlen = i; ++ ++ if (matchlen > strlen(word)) { ++ tmp = xstrdup(list[0]); ++ tmp[matchlen] = '\0'; ++ return tmp; + } + + return xstrdup(word); +@@ -2071,6 +2086,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path, + tmp2 = tmp + filelen - cesc; + len = strlen(tmp2); + /* quote argument on way out */ ++ mblen(NULL, 0); + for (i = 0; i < len; i += clen) { + if ((clen = mblen(tmp2 + i, len - i)) < 0 || + (size_t)clen > sizeof(ins) - 2) +-- +2.43.0 + diff --git a/backport-upstream-add-some-functions-to-free-various-structs.patch b/backport-upstream-add-some-functions-to-free-various-structs.patch new file mode 100644 index 0000000000000000000000000000000000000000..134b46d84d5d3871f6f3713bc9aea80870a45c05 --- /dev/null +++ b/backport-upstream-add-some-functions-to-free-various-structs.patch @@ -0,0 +1,159 @@ +From 4fddebe7f524b3403c876c3b399d5ce7ce3390a6 Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Thu, 25 Sep 2025 06:33:19 +0000 +Subject: upstream: add some functions to free various structs, including + +channels data and packet state; ok dtucker@ tb@ + +OpenBSD-Commit-ID: a8b3705309d632cdae370d4147a03e703087b0d1 +Conflict:Context adaptation of ssh_packet_close_internal in packet.c and channel_free_channels in channels.c and pwfree in misc.c +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=4fddebe7f524b3403c876c3b399d5ce7ce3390a6 +--- + channels.c | 19 +++++++++++++++++++ + channels.h | 3 ++- + misc.c | 19 +++++++++++++++++++ + misc.h | 1 + + packet.c | 13 +++++++++++++ + packet.h | 1 + + 6 files changed, 55 insertions(+), 1 deletion(-) + +diff --git a/channels.c b/channels.c +index 271a5dd..0f4f6b4 100644 +--- a/channels.c ++++ b/channels.c +@@ -790,6 +790,25 @@ channel_free_all(struct ssh *ssh) + sc->x11_fake_data_len = 0; + } + ++void ++channel_free_channels(struct ssh *ssh) ++{ ++ struct ssh_channels *sc; ++ ++ if (ssh == NULL || ssh->chanctxt == NULL) ++ return; ++ channel_free_all(ssh); ++ channel_clear_permission(ssh, FORWARD_USER, FORWARD_LOCAL); ++ channel_clear_permission(ssh, FORWARD_USER, FORWARD_REMOTE); ++ channel_clear_permission(ssh, FORWARD_ADM, FORWARD_LOCAL); ++ channel_clear_permission(ssh, FORWARD_ADM, FORWARD_REMOTE); ++ sc = ssh->chanctxt; ++ free(sc->channel_pre); ++ free(sc->channel_post); ++ freezero(sc, sizeof(*sc)); ++ ssh->chanctxt = NULL; ++} ++ + /* + * Closes the sockets/fds of all channels. This is used to close extra file + * descriptors after a fork. +diff --git a/channels.h b/channels.h +index 4fe7807..e926151 100644 +--- a/channels.h ++++ b/channels.h +@@ -278,8 +278,9 @@ struct Channel { + c->efd != -1 && (!(c->flags & (CHAN_EOF_RCVD|CHAN_CLOSE_RCVD)) || \ + sshbuf_len(c->extended) > 0)) + +-/* Add channel management structures to SSH transport instance */ ++/* Add/remove channel management structures to/from SSH transport instance */ + void channel_init_channels(struct ssh *ssh); ++void channel_free_channels(struct ssh *ssh); + + /* channel management */ + +diff --git a/misc.c b/misc.c +index 957c849..6226030 100644 +--- a/misc.c ++++ b/misc.c +@@ -506,6 +506,25 @@ pwcopy(struct passwd *pw) + return copy; + } + ++void ++pwfree(struct passwd *pw) ++{ ++ if (pw == NULL) ++ return; ++ free(pw->pw_name); ++ freezero(pw->pw_passwd, ++ pw->pw_passwd == NULL ? 0 : strlen(pw->pw_passwd)); ++#ifdef HAVE_STRUCT_PASSWD_PW_GECOS ++ free(pw->pw_gecos); ++#endif ++#ifdef HAVE_STRUCT_PASSWD_PW_CLASS ++ free(pw->pw_class); ++#endif ++ free(pw->pw_dir); ++ free(pw->pw_shell); ++ freezero(pw, sizeof(*pw)); ++} ++ + /* + * Convert ASCII string to TCP/IP port number. + * Port must be >=0 and <=65535. +diff --git a/misc.h b/misc.h +index 4e71675..312a9e8 100644 +--- a/misc.h ++++ b/misc.h +@@ -103,6 +103,7 @@ int lib_contains_symbol(const char *, const char *); + void sock_set_v6only(int); + + struct passwd *pwcopy(struct passwd *); ++void pwfree(struct passwd *); /* NB. only use with pwcopy */ + const char *ssh_gai_strerror(int); + + typedef void privdrop_fn(struct passwd *); +diff --git a/packet.c b/packet.c +index 5da9239..42fef28 100644 +--- a/packet.c ++++ b/packet.c +@@ -591,6 +591,7 @@ ssh_packet_close_internal(struct ssh *ssh, int do_close) + { + struct session_state *state = ssh->state; + u_int mode; ++ struct packet *p; + u_int had_keys = packet_state_has_keys(state); + + if (!state->initialized) +@@ -604,6 +605,11 @@ ssh_packet_close_internal(struct ssh *ssh, int do_close) + state->outgoing_packet = NULL; + sshbuf_free(state->incoming_packet); + state->incoming_packet = NULL; ++ while ((p = TAILQ_FIRST(&state->outgoing))) { ++ sshbuf_free(p->payload); ++ TAILQ_REMOVE(&state->outgoing, p, next); ++ free(p); ++ } + for (mode = 0; mode < MODE_MAX; mode++) { + kex_free_newkeys(state->newkeys[mode]); /* current keys */ + state->newkeys[mode] = NULL; +@@ -662,6 +668,13 @@ ssh_packet_close_internal(struct ssh *ssh, int do_close) + } + } + ++void ++ssh_packet_free(struct ssh *ssh) ++{ ++ ssh_packet_close_internal(ssh, 1); ++ freezero(ssh, sizeof(*ssh)); ++} ++ + void + ssh_packet_close(struct ssh *ssh) + { +diff --git a/packet.h b/packet.h +index c0158c1..3604bf3 100644 +--- a/packet.h ++++ b/packet.h +@@ -99,6 +99,7 @@ int ssh_packet_connection_af(struct ssh *); + void ssh_packet_set_nonblocking(struct ssh *); + int ssh_packet_get_connection_in(struct ssh *); + int ssh_packet_get_connection_out(struct ssh *); ++void ssh_packet_free(struct ssh *); + void ssh_packet_close(struct ssh *); + void ssh_packet_set_input_hook(struct ssh *, ssh_packet_hook_fn *, void *); + void ssh_packet_clear_keys(struct ssh *); +-- +2.43.0 + diff --git a/backport-upstream-don-t-abuse-SSHKEY_FLAG_EXT-to-signal.patch b/backport-upstream-don-t-abuse-SSHKEY_FLAG_EXT-to-signal.patch new file mode 100644 index 0000000000000000000000000000000000000000..f0ce0a7ad0517a7a01ff2f1e4670fa2f65ed5be7 --- /dev/null +++ b/backport-upstream-don-t-abuse-SSHKEY_FLAG_EXT-to-signal.patch @@ -0,0 +1,63 @@ +From e7b4b3f153713c15e3888aa50df039b2445492dd Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Thu, 9 Oct 2025 23:26:47 +0000 +Subject: upstream: don't abuse SSHKEY_FLAG_EXT to signal that a key is in + +the agent, as that triggers special handling on sshkey_free() + +OpenBSD-Commit-ID: 2ae2247babd2db167a30cf7a4f7eae4f26c000a8 +Conflict:NA +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=e7b4b3f153713c15e3888aa50df039b2445492dd +--- + ssh-keygen.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/ssh-keygen.c b/ssh-keygen.c +index 07aa1db..f15df41 100644 +--- a/ssh-keygen.c ++++ b/ssh-keygen.c +@@ -1780,7 +1780,7 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, + unsigned long long cert_serial, int cert_serial_autoinc, + int argc, char **argv) + { +- int r, i, found, agent_fd = -1; ++ int r, i, key_in_agent = 0, agent_fd = -1; + u_int n; + struct sshkey *ca, *public; + char valid[64], *otmp, *tmp, *cp, *out, *comment; +@@ -1809,17 +1809,19 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, + fatal_r(r, "Cannot use public key for CA signature"); + if ((r = ssh_fetch_identitylist(agent_fd, &agent_ids)) != 0) + fatal_r(r, "Retrieve agent key list"); +- found = 0; + for (j = 0; j < agent_ids->nkeys; j++) { + if (sshkey_equal(ca, agent_ids->keys[j])) { +- found = 1; ++ key_in_agent = 1; ++ /* Replace the CA key with the agent one */ ++ sshkey_free(ca); ++ ca = agent_ids->keys[j]; ++ agent_ids->keys[j] = NULL; + break; + } + } +- if (!found) ++ if (!key_in_agent) + fatal("CA key %s not found in agent", tmp); + ssh_free_identitylist(agent_ids); +- ca->flags |= SSHKEY_FLAG_EXT; + } else { + /* CA key is assumed to be a private key on the filesystem */ + ca = load_identity(tmp, NULL); +@@ -1884,7 +1886,7 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, + &public->cert->signature_key)) != 0) + fatal_r(r, "sshkey_from_private (ca key)"); + +- if (agent_fd != -1 && (ca->flags & SSHKEY_FLAG_EXT) != 0) { ++ if (key_in_agent) { + if ((r = sshkey_certify_custom(public, ca, + key_type_name, sk_provider, NULL, agent_signer, + &agent_fd)) != 0) +-- +2.43.0 + diff --git a/backport-upstream-during-sftp-uploads-avoid-a-condition-where-a-failed-write.patch b/backport-upstream-during-sftp-uploads-avoid-a-condition-where-a-failed-write.patch new file mode 100644 index 0000000000000000000000000000000000000000..ee1441ca906ee08f312e6691ea6d43d0198109f8 --- /dev/null +++ b/backport-upstream-during-sftp-uploads-avoid-a-condition-where-a-failed-write.patch @@ -0,0 +1,49 @@ +From 2c504a74ed81d13c8198a89ed1040d0fc5f73129 Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Tue, 30 Sep 2025 00:10:42 +0000 +Subject: upstream: during sftp uploads, avoid a condition where a failed write + +could be ignored if a subsequent write succeeded. + +This is unlikely but technically possible because sftp servers are +allowed to reorder requests. + +Reported by Graziano Stefani, ok tb@ + +OpenBSD-Commit-ID: 03904bce2c7f787223d01d7e1179fde15753eca3 +Conflict:NA +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=2c504a74ed81d13c8198a89ed1040d0fc5f73129 +--- + sftp-client.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/sftp-client.c b/sftp-client.c +index 544579a..c9f31ee 100644 +--- a/sftp-client.c ++++ b/sftp-client.c +@@ -2074,7 +2074,7 @@ sftp_upload(struct sftp_conn *conn, const char *local_path, + int fsync_flag, int inplace_flag) + { + int r, local_fd; +- u_int openmode, id, status = SSH2_FX_OK, reordered = 0; ++ u_int openmode, id, status = SSH2_FX_OK, status2, reordered = 0; + off_t offset, progress_counter; + u_char type, *handle, *data; + struct sshbuf *msg; +@@ -2211,9 +2211,11 @@ sftp_upload(struct sftp_conn *conn, const char *local_path, + fatal("Expected SSH2_FXP_STATUS(%d) packet, " + "got %d", SSH2_FXP_STATUS, type); + +- if ((r = sshbuf_get_u32(msg, &status)) != 0) ++ if ((r = sshbuf_get_u32(msg, &status2)) != 0) + fatal_fr(r, "parse status"); +- debug3("SSH2_FXP_STATUS %u", status); ++ debug3("SSH2_FXP_STATUS %u", status2); ++ if (status2 != SSH2_FX_OK) ++ status = status2; /* remember errors */ + + /* Find the request in our queue */ + if ((ack = request_find(&acks, rid)) == NULL) +-- +2.43.0 + diff --git a/backport-upstream-fix-leaks-of-struct-sftp_conn-in-scp.patch b/backport-upstream-fix-leaks-of-struct-sftp_conn-in-scp.patch new file mode 100644 index 0000000000000000000000000000000000000000..68ae5e3928f0ebdfeb4906234e9c6b84ecb2b313 --- /dev/null +++ b/backport-upstream-fix-leaks-of-struct-sftp_conn-in-scp.patch @@ -0,0 +1,124 @@ +From 6f5942454ad6756355f3b4983ab882cf15e44440 Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Mon, 15 Sep 2025 05:17:37 +0000 +Subject: upstream: fix leaks of struct sftp_conn in scp; ok dtucker@ + +OpenBSD-Commit-ID: 76bea50b5b87b750c3771bf80feb6067d994a9d2 +Conflict:adapted +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=6f5942454ad6756355f3b4983ab882cf15e44440 +--- + scp.c | 10 +++++++--- + sftp-client.c | 8 ++++++++ + sftp-client.h | 3 ++- + 3 files changed, 17 insertions(+), 4 deletions(-) + +diff --git a/scp.c b/scp.c +index e9813e8..c3f6f26 100644 +--- a/scp.c ++++ b/scp.c +@@ -1093,6 +1093,7 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) + if (mode == MODE_SFTP) { + if (remin == -1) { + /* Connect to dest now */ ++ sftp_free(conn); + conn = do_sftp_connect(thost, tuser, + tport, sftp_direct, + &remin, &remout, &do_cmd_pid); +@@ -1110,6 +1111,7 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) + * scp -3 hosta:/foo hosta:/bar hostb: + */ + /* Connect to origin now */ ++ sftp_free(conn2); + conn2 = do_sftp_connect(host, suser, + sport, sftp_direct, + &remin2, &remout2, &do_cmd_pid2); +@@ -1204,6 +1206,7 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) + } + if (remin == -1) { + /* Connect to remote now */ ++ sftp_free(conn); + conn = do_sftp_connect(thost, tuser, + tport, sftp_direct, + &remin, &remout, &do_cmd_pid); +@@ -1232,8 +1235,6 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) + } + } + out: +- if (mode == MODE_SFTP) +- free(conn); + free(tuser); + free(thost); + free(targ); +@@ -1241,6 +1242,8 @@ out: + free(suser); + free(host); + free(src); ++ sftp_free(conn); ++ sftp_free(conn2); + } + + void +@@ -1286,6 +1289,7 @@ tolocal(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) + } + /* Remote to local. */ + if (mode == MODE_SFTP) { ++ sftp_free(conn); + conn = do_sftp_connect(host, suser, sport, + sftp_direct, &remin, &remout, &do_cmd_pid); + if (conn == NULL) { +@@ -1297,7 +1301,6 @@ tolocal(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) + /* The protocol */ + sink_sftp(1, argv[argc - 1], src, conn); + +- free(conn); + (void) close(remin); + (void) close(remout); + remin = remout = -1; +@@ -1321,6 +1324,7 @@ tolocal(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) + free(suser); + free(host); + free(src); ++ sftp_free(conn); + } + + /* Prepare remote path, handling ~ by assuming cwd is the homedir */ +diff --git a/sftp-client.c b/sftp-client.c +index 2be448d..544579a 100644 +--- a/sftp-client.c ++++ b/sftp-client.c +@@ -611,6 +611,14 @@ sftp_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, + return ret; + } + ++void ++sftp_free(struct sftp_conn *conn) ++{ ++ if (conn == NULL) ++ return; ++ freezero(conn, sizeof(*conn)); ++} ++ + u_int + sftp_proto_version(struct sftp_conn *conn) + { +diff --git a/sftp-client.h b/sftp-client.h +index 00ed663..fe58651 100644 +--- a/sftp-client.h ++++ b/sftp-client.h +@@ -1,4 +1,4 @@ +-/* $OpenBSD: sftp-client.h,v 1.39 2023/09/08 05:56:13 djm Exp $ */ ++/* $OpenBSD: sftp-client.h,v 1.40 2025/09/15 05:17:37 djm Exp $ */ + + /* + * Copyright (c) 2001-2004 Damien Miller +@@ -71,6 +71,7 @@ struct sftp_limits { + * a pointer to a initialized sftp_conn struct on success. + */ + struct sftp_conn *sftp_init(int, int, u_int, u_int, u_int64_t); ++void sftp_free(struct sftp_conn *); + + u_int sftp_proto_version(struct sftp_conn *); + +-- +2.43.0 + diff --git a/backport-upstream-fix-memleak-of-channel-forwarding-permissions.patch b/backport-upstream-fix-memleak-of-channel-forwarding-permissions.patch new file mode 100644 index 0000000000000000000000000000000000000000..77cc0a225bbee01ecee7229e5b9a1aae58763a08 --- /dev/null +++ b/backport-upstream-fix-memleak-of-channel-forwarding-permissions.patch @@ -0,0 +1,37 @@ +From fae8e41741d23298c94a1ea3ef8704a1cc186cb5 Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Mon, 15 Sep 2025 04:39:58 +0000 +Subject: upstream: fix memleak of channel forwarding permissions; ok + +dtucker@ + +OpenBSD-Commit-ID: 069745547109bc8fcc09fab5b19c53599cae99fd +Conflict:NA +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=fae8e41741d23298c94a1ea3ef8704a1cc186cb5 +--- + channels.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/channels.c b/channels.c +index 2e95df4..271a5dd 100644 +--- a/channels.c ++++ b/channels.c +@@ -4507,10 +4507,13 @@ void + channel_clear_permission(struct ssh *ssh, int who, int where) + { + struct permission **permp; +- u_int *npermp; ++ u_int i, *npermp; + + permission_set_get_array(ssh, who, where, &permp, &npermp); +- *permp = xrecallocarray(*permp, *npermp, 0, sizeof(**permp)); ++ for (i = 0; i < *npermp; i++) ++ fwd_perm_clear((*permp) + i); ++ free(*permp); ++ *permp = NULL; + *npermp = 0; + } + +-- +2.43.0 + diff --git a/backport-upstream-fix-memleak-when-merging-auth-options-into-the-active-set.patch b/backport-upstream-fix-memleak-when-merging-auth-options-into-the-active-set.patch new file mode 100644 index 0000000000000000000000000000000000000000..ee618e853d0e101a673c06b1134a4e66383b03a7 --- /dev/null +++ b/backport-upstream-fix-memleak-when-merging-auth-options-into-the-active-set.patch @@ -0,0 +1,29 @@ +From 03872018c14ed943bc01a4e88be59195a742f106 Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Mon, 15 Sep 2025 04:39:15 +0000 +Subject: upstream: when merging auth options into the active set, don't + +leak the old struct sshauthopt; ok dtucker@ + +OpenBSD-Commit-ID: c6bfd7bc2932e37f811b3c53272c3b919d33e75b +Conflict:NA +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=03872018c14ed943bc01a4e88be59195a742f106 +--- + auth.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/auth.c b/auth.c +index 83b5318..7873cf9 100644 +--- a/auth.c ++++ b/auth.c +@@ -740,6 +740,7 @@ auth_activate_options(struct ssh *ssh, struct sshauthopt *opts) + error("Inconsistent authentication options: %s", emsg); + return -1; + } ++ sshauthopt_free(old); + return 0; + } + +-- +2.43.0 + diff --git a/backport-upstream-fix-memory-leak-in-mux_client_request_stdio_fwd.patch b/backport-upstream-fix-memory-leak-in-mux_client_request_stdio_fwd.patch new file mode 100644 index 0000000000000000000000000000000000000000..b5f4255edac94296b74c4a7c380e220573c48d03 --- /dev/null +++ b/backport-upstream-fix-memory-leak-in-mux_client_request_stdio_fwd.patch @@ -0,0 +1,33 @@ +From 42b14ff1e06fd683c7d15a6b2816c16108873a5a Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Tue, 30 Sep 2025 00:03:09 +0000 +Subject: upstream: fix memory leak in mux_client_request_stdio_fwd GHPR#575 + +by Boris Tonofa; ok dtucker + +OpenBSD-Commit-ID: 410cdd05242304bd0196b9172ce5fcaf89d2d8ce +Conflict:NA +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=42b14ff1e06fd683c7d15a6b2816c16108873a5a +--- + mux.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/mux.c b/mux.c +index 7000077..3a061fd 100644 +--- a/mux.c ++++ b/mux.c +@@ -2204,8 +2204,10 @@ mux_client_request_stdio_fwd(int fd) + sshbuf_reset(m); + if (mux_client_read_packet(fd, m) != 0) { + if (errno == EPIPE || +- (errno == EINTR && muxclient_terminate != 0)) ++ (errno == EINTR && muxclient_terminate != 0)) { ++ sshbuf_free(m); + return 0; ++ } + fatal_f("mux_client_read_packet: %s", strerror(errno)); + } + fatal_f("master returned unexpected message %u", type); +-- +2.43.0 + diff --git a/backport-upstream-fix-some-leaks-feedback.patch b/backport-upstream-fix-some-leaks-feedback.patch new file mode 100644 index 0000000000000000000000000000000000000000..cb2f60ae9acd3fa8157feb6b39786289b3495102 --- /dev/null +++ b/backport-upstream-fix-some-leaks-feedback.patch @@ -0,0 +1,96 @@ +From a8a2702bcd9e81a086e6d2c278f1b62f9d8bf3a1 Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Thu, 25 Sep 2025 06:57:54 +0000 +Subject: upstream: fix some leaks; feedback/ok dtucker@ + +OpenBSD-Commit-ID: 05bdbc2e494b87a4a79e509020bd8249c86a4ff0 +Conflict:Context adaption of main function +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=a8a2702bcd9e81a086e6d2c278f1b62f9d8bf3a1 +--- + ssh-add.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 48 insertions(+), 1 deletion(-) + +diff --git a/ssh-add.c b/ssh-add.c +index 1ed62bc..56ee69e 100644 +--- a/ssh-add.c ++++ b/ssh-add.c +@@ -724,6 +724,47 @@ stringlist_append(char ***listp, const char *s) + (*listp)[i] = xstrdup(s); + } + ++static void ++stringlist_free(char **list) ++{ ++ size_t i = 0; ++ ++ if (list == NULL) ++ return; ++ for (i = 0; list[i] != NULL; i++) ++ free(list[i]); ++ free(list); ++} ++ ++static void ++free_dest_constraint_hop(struct dest_constraint_hop *dch) ++{ ++ u_int i; ++ ++ if (dch == NULL) ++ return; ++ free(dch->user); ++ free(dch->hostname); ++ for (i = 0; i < dch->nkeys; i++) ++ sshkey_free(dch->keys[i]); ++ free(dch->keys); ++ free(dch->key_is_ca); ++} ++ ++static void ++free_dest_constraints(struct dest_constraint **dcs, size_t ndcs) ++{ ++ size_t i; ++ ++ for (i = 0; i < ndcs; i++) { ++ free_dest_constraint_hop(&dcs[i]->from); ++ free_dest_constraint_hop(&dcs[i]->to); ++ free(dcs[i]); ++ } ++ free(dcs); ++} ++ ++ + static void + parse_dest_constraint_hop(const char *s, struct dest_constraint_hop *dch, + char **hostkey_files) +@@ -857,7 +898,7 @@ main(int argc, char **argv) + LogLevel log_level = SYSLOG_LEVEL_INFO; + struct sshkey *k, **certs = NULL; + struct dest_constraint **dest_constraints = NULL; +- size_t ndest_constraints = 0i, ncerts = 0; ++ size_t n, ndest_constraints = 0, ncerts = 0; + + /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ + sanitise_stdfd(); +@@ -1041,6 +1082,9 @@ main(int argc, char **argv) + dest_constraints, ndest_constraints, + certs, ncerts, NULL) == -1) + ret = 1; ++ for (n = 0; n < ncerts; n++) ++ sshkey_free(certs[n]); ++ free(certs); + goto done; + } + if (do_download) { +@@ -1088,6 +1132,9 @@ main(int argc, char **argv) + } + done: + clear_pass(); ++ stringlist_free(hostkey_files); ++ stringlist_free(dest_constraint_strings); ++ free_dest_constraints(dest_constraints, ndest_constraints); + ssh_close_authentication_socket(agent_fd); + return ret; + } +-- +2.43.0 + diff --git a/backport-upstream-fix-some-one-off-leaks-in-ssh-keygen.patch b/backport-upstream-fix-some-one-off-leaks-in-ssh-keygen.patch new file mode 100644 index 0000000000000000000000000000000000000000..9957ccfa84aaade7ec7d35a23124ff8cf83aab33 --- /dev/null +++ b/backport-upstream-fix-some-one-off-leaks-in-ssh-keygen.patch @@ -0,0 +1,235 @@ +From 846987d1233f24bbe87ebed347e328f45525388a Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Thu, 25 Sep 2025 07:04:38 +0000 +Subject: upstream: fix some one-off leaks in ssh-keygen; ok dtucker@ + +OpenBSD-Commit-ID: 32f51289c93246474659aa49067926fcab9e02e8 +Conflict:Context adaption for do_convert_private_ssh2,update_krl_from_file,main +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=846987d1233f24bbe87ebed347e328f45525388a +--- + ssh-keygen.c | 55 +++++++++++++++++++++++++++++----------------------- + 1 file changed, 31 insertions(+), 24 deletions(-) + +diff --git a/ssh-keygen.c b/ssh-keygen.c +index 3e552e0..07aa1db 100644 +--- a/ssh-keygen.c ++++ b/ssh-keygen.c +@@ -380,7 +380,6 @@ do_convert_to_ssh2(struct passwd *pw, struct sshkey *k) + fprintf(stdout, "Comment: \"%s\"\n%s", comment, b64); + fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END); + free(b64); +- exit(0); + } + + static void +@@ -405,7 +404,6 @@ do_convert_to_pkcs8(struct sshkey *k) + default: + fatal_f("unsupported key type %s", sshkey_type(k)); + } +- exit(0); + } + + static void +@@ -430,7 +428,6 @@ do_convert_to_pem(struct sshkey *k) + default: + fatal_f("unsupported key type %s", sshkey_type(k)); + } +- exit(0); + } + + static void +@@ -459,7 +456,6 @@ do_convert_to(struct passwd *pw) + default: + fatal_f("unknown key format %d", convert_format); + } +- exit(0); + } + + /* +@@ -745,7 +741,6 @@ do_convert_from_pkcs8(struct sshkey **k, int *private) + EVP_PKEY_base_id(pubkey)); + } + EVP_PKEY_free(pubkey); +- return; + } + + static void +@@ -822,7 +817,6 @@ do_convert_from(struct passwd *pw) + if (!ok) + fatal("key write failed"); + sshkey_free(k); +- exit(0); + } + #endif + +@@ -1933,16 +1927,17 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, + + sshkey_free(public); + free(out); ++ free(comment); + if (cert_serial_autoinc) + cert_serial++; + } + if (pin != NULL) + freezero(pin, strlen(pin)); ++ sshkey_free(ca); + free(ca_fp); + #ifdef ENABLE_PKCS11 + pkcs11_terminate(); + #endif +- exit(0); + } + + static u_int64_t +@@ -3364,9 +3359,9 @@ main(int argc, char **argv) + { + char comment[1024], *passphrase = NULL; + char *rr_hostname = NULL, *ep, *fp, *ra; +- struct sshkey *private, *public; ++ struct sshkey *private = NULL, *public = NULL; + struct passwd *pw; +- int r, opt, type; ++ int ret = 0, r, opt, type; + int change_passphrase = 0, change_comment = 0, show_cert = 0; + int find_host = 0, delete_host = 0, hash_hosts = 0; + int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0; +@@ -3627,8 +3622,9 @@ main(int argc, char **argv) + "missing allowed keys file"); + exit(1); + } +- return sig_find_principals(ca_key_path, identity_file, ++ ret = sig_find_principals(ca_key_path, identity_file, + opts, nopts); ++ goto done; + } else if (strncmp(sign_op, "match-principals", 16) == 0) { + if (!have_identity) { + error("Too few arguments for match-principals:" +@@ -3640,8 +3636,9 @@ main(int argc, char **argv) + "missing principal ID"); + exit(1); + } +- return sig_match_principals(identity_file, cert_key_id, ++ ret = sig_match_principals(identity_file, cert_key_id, + opts, nopts); ++ goto done; + } else if (strncmp(sign_op, "sign", 4) == 0) { + /* NB. cert_principals is actually namespace, via -n */ + if (cert_principals == NULL || +@@ -3655,8 +3652,9 @@ main(int argc, char **argv) + "missing key"); + exit(1); + } +- return sig_sign(identity_file, cert_principals, ++ ret = sig_sign(identity_file, cert_principals, + prefer_agent, argc, argv, opts, nopts); ++ goto done; + } else if (strncmp(sign_op, "check-novalidate", 16) == 0) { + /* NB. cert_principals is actually namespace, via -n */ + if (cert_principals == NULL || +@@ -3670,8 +3668,9 @@ main(int argc, char **argv) + "missing signature file"); + exit(1); + } +- return sig_verify(ca_key_path, cert_principals, ++ ret = sig_verify(ca_key_path, cert_principals, + NULL, NULL, NULL, opts, nopts); ++ goto done; + } else if (strncmp(sign_op, "verify", 6) == 0) { + /* NB. cert_principals is actually namespace, via -n */ + if (cert_principals == NULL || +@@ -3695,9 +3694,10 @@ main(int argc, char **argv) + "missing principal identity"); + exit(1); + } +- return sig_verify(ca_key_path, cert_principals, ++ ret = sig_verify(ca_key_path, cert_principals, + cert_key_id, identity_file, rr_hostname, + opts, nopts); ++ goto done; + } + error("Unsupported operation for -Y: \"%s\"", sign_op); + usage(); +@@ -3725,11 +3725,11 @@ main(int argc, char **argv) + if (gen_krl) { + do_gen_krl(pw, update_krl, ca_key_path, + cert_serial, identity_comment, argc, argv); +- return (0); ++ goto done; + } + if (check_krl) { + do_check_krl(pw, print_fingerprint, argc, argv); +- return (0); ++ goto done; + } + if (ca_key_path != NULL) { + if (cert_key_id == NULL) +@@ -3738,6 +3738,7 @@ main(int argc, char **argv) + add_cert_option(opts[i]); + do_ca_sign(pw, ca_key_path, prefer_agent, + cert_serial, cert_serial_autoinc, argc, argv); ++ goto done; + } + if (show_cert) + do_show_cert(pw); +@@ -3756,7 +3757,8 @@ main(int argc, char **argv) + "FIDO authenticator download", opts[i]); + } + } +- return do_download_sk(sk_provider, sk_device); ++ ret = do_download_sk(sk_provider, sk_device); ++ goto done; + } + if (print_fingerprint || print_bubblebabble) + do_fingerprint(pw); +@@ -3765,10 +3767,14 @@ main(int argc, char **argv) + if (change_comment) + do_change_comment(pw, identity_comment); + #ifdef WITH_OPENSSL +- if (convert_to) ++ if (convert_to) { + do_convert_to(pw); +- if (convert_from) ++ goto done; ++ } ++ if (convert_from) { + do_convert_from(pw); ++ goto done; ++ } + #else /* WITH_OPENSSL */ + if (convert_to || convert_from) + fatal("key conversion disabled at compile time"); +@@ -3815,16 +3821,16 @@ main(int argc, char **argv) + } + if (do_gen_candidates) { + do_moduli_gen(argv[0], opts, nopts); +- return 0; ++ goto done; + } + if (do_screen_candidates) { + do_moduli_screen(argv[0], opts, nopts); +- return 0; ++ goto done; + } + + if (gen_all_hostkeys) { + do_gen_all_hostkeys(pw); +- return (0); ++ goto done; + } + + if (key_type_name == NULL) +@@ -3979,8 +3985,9 @@ main(int argc, char **argv) + if (sk_attestation_path != NULL) + save_attestation(attest, sk_attestation_path); + ++ done: + sshbuf_free(attest); + sshkey_free(public); +- +- exit(0); ++ pwfree(pw); ++ exit(ret); + } +-- +2.43.0 + diff --git a/backport-upstream-fix-some-one-off-leaks-in-ssh.patch b/backport-upstream-fix-some-one-off-leaks-in-ssh.patch new file mode 100644 index 0000000000000000000000000000000000000000..e6f9b7b5fb75694dda3af14c93b0f21fad388b22 --- /dev/null +++ b/backport-upstream-fix-some-one-off-leaks-in-ssh.patch @@ -0,0 +1,43 @@ +From 8235dc3d82c0ac347a3600df0907c6573720fbaa Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Thu, 25 Sep 2025 07:05:11 +0000 +Subject: upstream: fix some one-off leaks in ssh.c; ok dtucker@ + +OpenBSD-Commit-ID: bf3c27ffe4b3cccb6553b554ec4c04929065a2bc +Conflict:NA +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=8235dc3d82c0ac347a3600df0907c6573720fbaa +--- + ssh.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/ssh.c b/ssh.c +index 4e33c5d..2745bd7 100644 +--- a/ssh.c ++++ b/ssh.c +@@ -1670,8 +1670,6 @@ main(int ac, char **av) + &timeout_ms, options.tcp_keep_alive) != 0) + exit(255); + +- if (addrs != NULL) +- freeaddrinfo(addrs); + + ssh_packet_set_timeout(ssh, options.server_alive_interval, + options.server_alive_count_max); +@@ -1819,9 +1817,13 @@ main(int ac, char **av) + pkcs11_terminate(); + + skip_connect: ++ if (addrs != NULL) ++ freeaddrinfo(addrs); + exit_status = ssh_session2(ssh, cinfo); + ssh_conn_info_free(cinfo); +- ssh_packet_close(ssh); ++ channel_free_channels(ssh); ++ ssh_packet_free(ssh); ++ pwfree(pw); + + if (options.control_path != NULL && muxserver_sock != -1) + unlink(options.control_path); +-- +2.43.0 + diff --git a/backport-upstream-ix-memleak-when-applying-certificate-options.patch b/backport-upstream-ix-memleak-when-applying-certificate-options.patch new file mode 100644 index 0000000000000000000000000000000000000000..8b64abc89bb05397a3fa5d2f8a0450b80b7ca071 --- /dev/null +++ b/backport-upstream-ix-memleak-when-applying-certificate-options.patch @@ -0,0 +1,35 @@ +From efed5da4ced88170cf474246eff771dd16c7092f Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Mon, 15 Sep 2025 04:38:00 +0000 +Subject: upstream: fix memleak when applying certificate options; ok + +dtucker + +OpenBSD-Commit-ID: 36c219dcc05f4df82a0f9c500bdf5dbfea925289 +Conflict:NA +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=efed5da4ced88170cf474246eff771dd16c7092f +--- + auth-options.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/auth-options.c b/auth-options.c +index c89b1ee..c6eb23e 100644 +--- a/auth-options.c ++++ b/auth-options.c +@@ -1,4 +1,4 @@ +-/* $OpenBSD: auth-options.c,v 1.101 2023/07/14 07:44:21 dtucker Exp $ */ ++/* $OpenBSD: auth-options.c,v 1.102 2025/09/15 04:38:00 djm Exp $ */ + /* + * Copyright (c) 2018 Damien Miller + * +@@ -157,6 +157,7 @@ cert_option_list(struct sshauthopt *opts, struct sshbuf *oblob, + if (addr_match_cidr_list(NULL, allowed) == -1) { + error("Certificate source-address " + "contents invalid"); ++ free(allowed); + goto out; + } + opts->required_from_host_cert = allowed; +-- +2.43.0 + diff --git a/backport-upstream-leak-of-principals-file-lines.patch b/backport-upstream-leak-of-principals-file-lines.patch new file mode 100644 index 0000000000000000000000000000000000000000..35864777fe8c2ef2a6b85a9eab731b0ea90c4388 --- /dev/null +++ b/backport-upstream-leak-of-principals-file-lines.patch @@ -0,0 +1,27 @@ +From 52f38c76fcb38dfe619d8caa3bb4bb782c785026 Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Mon, 15 Sep 2025 04:52:41 +0000 +Subject: upstream: leak of principals file lines; ok dtucker@ + +OpenBSD-Commit-ID: 918bf1b70e5a969059300f3c23d45911690d9015 +Conflict:NA +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=52f38c76fcb38dfe619d8caa3bb4bb782c785026 +--- + sshsig.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sshsig.c b/sshsig.c +index 1b7f40d..b073245 100644 +--- a/sshsig.c ++++ b/sshsig.c +@@ -1118,6 +1118,7 @@ sshsig_match_principals(const char *path, const char *principal, + linesize = 0; + } + fclose(f); ++ free(line); + + if (ret == 0) { + if (nprincipals == 0) +-- +2.43.0 + diff --git a/backport-upstream-memleak-of-KRL-revoked-certs-struct.patch b/backport-upstream-memleak-of-KRL-revoked-certs-struct.patch new file mode 100644 index 0000000000000000000000000000000000000000..37e67ae15463f333635c7de4288d8bc2615c778f --- /dev/null +++ b/backport-upstream-memleak-of-KRL-revoked-certs-struct.patch @@ -0,0 +1,36 @@ +From d68451a25808c4eee74b898873cd4761f73651ed Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Mon, 15 Sep 2025 04:41:20 +0000 +Subject: upstream: memleak of KRL revoked certs struct; ok dtucker + +OpenBSD-Commit-ID: f319868e0b2de49c41c735e75b87c403f009f5f9 +Conflict:NA +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=d68451a25808c4eee74b898873cd4761f73651ed +--- + krl.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/krl.c b/krl.c +index cec61a8..837cc55 100644 +--- a/krl.c ++++ b/krl.c +@@ -149,6 +149,8 @@ revoked_certs_free(struct revoked_certs *rc) + struct revoked_serial *rs, *trs; + struct revoked_key_id *rki, *trki; + ++ if (rc == NULL) ++ return; + RB_FOREACH_SAFE(rs, revoked_serial_tree, &rc->revoked_serials, trs) { + RB_REMOVE(revoked_serial_tree, &rc->revoked_serials, rs); + free(rs); +@@ -159,6 +161,7 @@ revoked_certs_free(struct revoked_certs *rc) + free(rki); + } + sshkey_free(rc->ca_key); ++ freezero(rc, sizeof(*rc)); + } + + void +-- +2.43.0 + diff --git a/backport-upstream-memleak-of-certificate-path.patch b/backport-upstream-memleak-of-certificate-path.patch new file mode 100644 index 0000000000000000000000000000000000000000..fd70a8ead7346a7b4b8ed11662c77f227a83f838 --- /dev/null +++ b/backport-upstream-memleak-of-certificate-path.patch @@ -0,0 +1,27 @@ +From ee99f6e93e0ee90eedbd27ffb9b7f9fef7b98010 Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Mon, 15 Sep 2025 04:50:42 +0000 +Subject: upstream: memleak of certificate path; ok dtucker@ + +OpenBSD-Commit-ID: 90dc5390f2756ba339e2e6df54d4b8651d64c1e7 +Conflict:NA +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=ee99f6e93e0ee90eedbd27ffb9b7f9fef7b98010 +--- + ssh.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/ssh.c b/ssh.c +index 02f4f7d..4e33c5d 100644 +--- a/ssh.c ++++ b/ssh.c +@@ -2399,6 +2399,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo) + free(cp); + continue; + } ++ free(cp); + /* NB. leave filename pointing to private key */ + identity_files[n_ids] = xstrdup(filename); + identity_keys[n_ids] = public; +-- +2.43.0 + diff --git a/backport-upstream-memleak-of-editline-history.patch b/backport-upstream-memleak-of-editline-history.patch new file mode 100644 index 0000000000000000000000000000000000000000..23946da8cf6df90c28997c2279c0c97eb8273728 --- /dev/null +++ b/backport-upstream-memleak-of-editline-history.patch @@ -0,0 +1,28 @@ +From bc60bd55cbc1f8139c840668733b51475cbefd93 Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Mon, 15 Sep 2025 04:49:00 +0000 +Subject: upstream: memleak of editline history; ok dtucker@ + +OpenBSD-Commit-ID: a244c54eb074cf7fbe28f7ac4f03ace270f7a999 +Conflict:NA +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=bc60bd55cbc1f8139c840668733b51475cbefd93 +--- + sftp.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sftp.c b/sftp.c +index 608089e..cab44a9 100644 +--- a/sftp.c ++++ b/sftp.c +@@ -2347,6 +2347,8 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) + free(conn); + + #ifdef USE_LIBEDIT ++ if (hl != NULL) ++ history_end(hl); + if (el != NULL) + el_end(el); + #endif /* USE_LIBEDIT */ +-- +2.43.0 + diff --git a/backport-upstream-memleak-of-kex-server_sig_algs.patch b/backport-upstream-memleak-of-kex-server_sig_algs.patch new file mode 100644 index 0000000000000000000000000000000000000000..ed982a4b6d4dd0820b4483ad8ff457ee737aad4a --- /dev/null +++ b/backport-upstream-memleak-of-kex-server_sig_algs.patch @@ -0,0 +1,27 @@ +From 67940cc2f329427d3acb64d4893faf4527e58d5c Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Mon, 15 Sep 2025 04:40:34 +0000 +Subject: upstream: memleak of kex->server_sig_algs; ok dtucker@ + +OpenBSD-Commit-ID: 41a3f64edd2c9b8addb2e445514ae25c24819e2c +Conflict:NA +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=67940cc2f329427d3acb64d4893faf4527e58d5c +--- + kex.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/kex.c b/kex.c +index f357d02..1b4a60c 100644 +--- a/kex.c ++++ b/kex.c +@@ -1035,6 +1035,7 @@ kex_free(struct kex *kex) + free(kex->failed_choice); + free(kex->hostkey_alg); + free(kex->name); ++ free(kex->server_sig_algs); + free(kex); + } + +-- +2.43.0 + diff --git a/backport-upstream-memleak-of-rfwd-callback-context.patch b/backport-upstream-memleak-of-rfwd-callback-context.patch new file mode 100644 index 0000000000000000000000000000000000000000..53db630081a0b79f1c2382cb3614a6577f2e2721 --- /dev/null +++ b/backport-upstream-memleak-of-rfwd-callback-context.patch @@ -0,0 +1,27 @@ +From ee77ab9b2ca2d70daf8d4352f5daffa8036ece64 Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Mon, 15 Sep 2025 04:48:29 +0000 +Subject: upstream: memleak of rfwd callback context; ok dtucker@ + +OpenBSD-Commit-ID: 70b2aafeaace90703dd16a44a2a0b723d9155f33 +Conflict:NA +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=ee77ab9b2ca2d70daf8d4352f5daffa8036ece64 +--- + mux.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/mux.c b/mux.c +index d377127..7000077 100644 +--- a/mux.c ++++ b/mux.c +@@ -677,6 +677,7 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) + if (c->mux_pause <= 0) + fatal_f("mux_pause %d", c->mux_pause); + c->mux_pause = 0; /* start processing messages again */ ++ free(fctx); + } + + static int +-- +2.43.0 + diff --git a/backport-upstream-similar-to-scp-fix-implicit-destination-path-selection.patch b/backport-upstream-similar-to-scp-fix-implicit-destination-path-selection.patch new file mode 100644 index 0000000000000000000000000000000000000000..dcb7991d27918d008c56fda24f04e35ef0fb3594 --- /dev/null +++ b/backport-upstream-similar-to-scp-fix-implicit-destination-path-selection.patch @@ -0,0 +1,42 @@ +From 4f14ca8633a2c8c0a1a19165663421f0ab32f6ab Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Mon, 13 Oct 2025 00:54:29 +0000 +Subject: upstream: similar to scp, fix implicit destination path selection + +when source path ends with ".."; ok deraadt@ + +OpenBSD-Commit-ID: 9b8d2a662d96b241293a88b3ea21f2419bfc4812 +Conflict:NA +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=4f14ca8633a2c8c0a1a19165663421f0ab32f6ab +--- + sftp.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/sftp.c b/sftp.c +index 93868e7..8bc1fea 100644 +--- a/sftp.c ++++ b/sftp.c +@@ -685,6 +685,10 @@ process_get(struct sftp_conn *conn, const char *src, const char *dst, + goto out; + } + ++ /* Special handling for dest of '..' */ ++ if (strcmp(filename, "..") == 0) ++ filename = "."; /* Download to dest, not dest/.. */ ++ + if (g.gl_matchc == 1 && dst) { + if (local_is_dir(dst)) { + abs_dst = sftp_path_append(dst, filename); +@@ -779,6 +783,9 @@ process_put(struct sftp_conn *conn, const char *src, const char *dst, + err = -1; + goto out; + } ++ /* Special handling for source of '..' */ ++ if (strcmp(filename, "..") == 0) ++ filename = "."; /* Upload to dest, not dest/.. */ + + free(abs_dst); + abs_dst = NULL; +-- +2.43.0 + diff --git a/backport-upstream-when-using-the-SFTP-protocol-for-transfers-fix-implicit.patch b/backport-upstream-when-using-the-SFTP-protocol-for-transfers-fix-implicit.patch new file mode 100644 index 0000000000000000000000000000000000000000..e65226b945e4be8894f4b869bb4bd85c9e3b30dc --- /dev/null +++ b/backport-upstream-when-using-the-SFTP-protocol-for-transfers-fix-implicit.patch @@ -0,0 +1,44 @@ +From 6432b9f6a216d0f5fb43df500e9bc30bebb3f58b Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Mon, 13 Oct 2025 00:53:51 +0000 +Subject: upstream: when using the SFTP protocol for transfers, fix implicit + +destination path selection when source path ends with ".."; ok deraadt@ +bz3871 + +OpenBSD-Commit-ID: d75b3b006386c5302ed4f67c4add18464ab36a0b +Conflict:NA +Reference:https://anongit.mindrot.org/openssh.git/commit/?id=6432b9f6a216d0f5fb43df500e9bc30bebb3f58b +--- + scp.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/scp.c b/scp.c +index c3f6f26..29c06b9 100644 +--- a/scp.c ++++ b/scp.c +@@ -1366,6 +1366,10 @@ source_sftp(int argc, char *src, char *targ, struct sftp_conn *conn) + if ((filename = basename(src)) == NULL) + fatal("basename \"%s\": %s", src, strerror(errno)); + ++ /* Special handling for source of '..' */ ++ if (strcmp(filename, "..") == 0) ++ filename = "."; /* Upload to dest, not dest/.. */ ++ + /* + * No need to glob here - the local shell already took care of + * the expansions +@@ -1639,6 +1643,10 @@ sink_sftp(int argc, char *dst, const char *src, struct sftp_conn *conn) + goto out; + } + ++ /* Special handling for destination of '..' */ ++ if (strcmp(filename, "..") == 0) ++ filename = "."; /* Download to dest, not dest/.. */ ++ + if (dst_is_dir) + abs_dst = sftp_path_append(dst, filename); + else +-- +2.43.0 + diff --git a/openssh.spec b/openssh.spec index d712e1e44c272db5844aa0f0905afe65ac5b3c5a..7693114f205763d1632988c758cc73013d888b98 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 9 +%global openssh_release 10 Name: openssh Version: 9.6p1 @@ -116,6 +116,29 @@ Patch75: backport-fix-CVE-2025-26466.patch Patch76: backport-fix-CVE-2025-32728.patch Patch77: backport-fix-CVE-2025-61984.patch Patch78: backport-fix-CVE-2025-61985.patch +Patch79: backport-upstream-ix-memleak-when-applying-certificate-options.patch +Patch80: backport-upstream-fix-memleak-when-merging-auth-options-into-the-active-set.patch +Patch81: backport-upstream-fix-memleak-of-channel-forwarding-permissions.patch +Patch82: backport-upstream-memleak-of-kex-server_sig_algs.patch +Patch83: backport-upstream-memleak-of-KRL-revoked-certs-struct.patch +Patch84: backport-upstream-memleak-of-rfwd-callback-context.patch +Patch85: backport-upstream-memleak-of-editline-history.patch +Patch86: backport-upstream-memleak-of-certificate-path.patch +Patch87: backport-upstream-fix-leaks-of-struct-sftp_conn-in-scp.patch +Patch88: backport-upstream-leak-of-principals-file-lines.patch +Patch89: backport-upstream-add-some-functions-to-free-various-structs.patch +Patch90: backport-upstream-fix-some-leaks-feedback.patch +Patch91: backport-upstream-fix-some-one-off-leaks-in-ssh-keygen.patch +Patch92: backport-upstream-fix-some-one-off-leaks-in-ssh.patch +Patch93: backport-Remove-status-bits-from-OpenSSL-3-version-check.patch +Patch94: backport-ensure-struct-passwd-fields-are-non-NULL-in-pwcopy.patch +Patch95: backport-upstream-fix-memory-leak-in-mux_client_request_stdio_fwd.patch +Patch96: backport-upstream-during-sftp-uploads-avoid-a-condition-where-a-failed-write.patch +Patch97: backport-upstream-When-tab-completing-a-filename-ensure-that-the-completed.patch +Patch98: backport-upstream-don-t-abuse-SSHKEY_FLAG_EXT-to-signal.patch +Patch99: backport-upstream-when-using-the-SFTP-protocol-for-transfers-fix-implicit.patch +Patch100: backport-upstream-similar-to-scp-fix-implicit-destination-path-selection.patch +Patch101: backport-upstream-Activate-UnusedConnectionTimeout-only-after-last-channel.patch Requires: /sbin/nologin Requires: libselinux >= 2.3-5 audit-libs >= 1.0.8 @@ -318,6 +341,29 @@ popd %patch -P 76 -p1 %patch -P 77 -p1 %patch -P 78 -p1 +%patch -P 79 -p1 +%patch -P 80 -p1 +%patch -P 81 -p1 +%patch -P 82 -p1 +%patch -P 83 -p1 +%patch -P 84 -p1 +%patch -P 85 -p1 +%patch -P 86 -p1 +%patch -P 87 -p1 +%patch -P 88 -p1 +%patch -P 89 -p1 +%patch -P 90 -p1 +%patch -P 91 -p1 +%patch -P 92 -p1 +%patch -P 93 -p1 +%patch -P 94 -p1 +%patch -P 95 -p1 +%patch -P 96 -p1 +%patch -P 97 -p1 +%patch -P 98 -p1 +%patch -P 99 -p1 +%patch -P 100 -p1 +%patch -P 101 -p1 autoreconf pushd pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4 @@ -549,6 +595,12 @@ fi %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Tue Dec 02 2025 zhaoyonghao - 9.6p1-10 +- Type:bugfix +- CVE:NA +- SUG:NA +- DESC:backport some patches from upstream + * Fri Oct 24 2025 zhangbinqin - 9.6p1-9 - Type:CVE - CVE:CVE-2025-61984 CVE-2025-61985