1
0
mirror of https://git.yoctoproject.org/poky synced 2026-08-30 00:26:36 +00:00

openssh: Fix CVE-2026-60002

This patch applies the upstream OpenSSH 10.4 backport for
CVE-2026-60002. The upstream fix commit is referenced in [1],
and the public CVE advisory is referenced in [2].

[1] https://github.com/openssh/openssh-portable/commit/e8bdfb151a356d0171fea4194dd205fbb252be23
[2] https://nvd.nist.gov/vuln/detail/CVE-2026-60002

(From OE-Core rev: c46f65e3f938efa983b24c53206972972d51da24)

Signed-off-by: Devansh Patel <devanshp@cisco.com>
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
Signed-off-by: Paul Barker <paul@pbarker.dev>
This commit is contained in:
Devansh Patel
2026-07-20 11:57:48 -07:00
committed by Paul Barker
parent b2a7dabed0
commit cb5e6f65a5
2 changed files with 227 additions and 0 deletions
@@ -0,0 +1,226 @@
From 767104acedd68c317b9d8fb603561e1a8be9e76a Mon Sep 17 00:00:00 2001
From: "djm@openbsd.org" <djm@openbsd.org>
Date: Mon, 6 Jul 2026 07:49:58 +0000
Subject: [PATCH] upstream: fix ownership and lifetime of several bits of
client
state that need to persist for the life of the connection, especially the
cached hostkey that was being incorrectly freed early on some paths, possibly
allowing its use after free.
Reported by Zhenpeng (Leo) Lin from depthfirst.com
CVE: CVE-2026-60002
Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/e8bdfb151a356d0171fea4194dd205fbb252be23]
Backport Changes:
- Retained Scarthgap's valid_hostname() and valid_ruser() helpers when
relocating ssh_conn_info_free() from ssh.c to sshconnect.c.
- Retained Scarthgap's ext-info-c proposal handling while applying the
upstream connection-state ownership and lifetime changes.
- Retained the Scarthgap OpenBSD revision identifiers in ssh.c,
sshconnect.c, sshconnect.h, and sshconnect2.c.
OpenBSD-Commit-ID: faaa6ad72e7d69d41fa8b197b606265b7d9bc73f
(cherry picked from commit e8bdfb151a356d0171fea4194dd205fbb252be23)
Signed-off-by: Devansh Patel <devanshp@cisco.com>
---
ssh.c | 24 ++----------------------
sshconnect.c | 47 +++++++++++++++++++++++++++++++++++++++++++++--
sshconnect.h | 7 +++++--
sshconnect2.c | 20 +++++++++++---------
4 files changed, 63 insertions(+), 35 deletions(-)
diff --git a/ssh.c b/ssh.c
index 9c49f98a8..aecdb79ea 100644
--- a/ssh.c
+++ b/ssh.c
@@ -606,26 +606,6 @@ set_addrinfo_port(struct addrinfo *addrs, int port)
}
}
-static void
-ssh_conn_info_free(struct ssh_conn_info *cinfo)
-{
- if (cinfo == NULL)
- return;
- free(cinfo->conn_hash_hex);
- free(cinfo->shorthost);
- free(cinfo->uidstr);
- free(cinfo->keyalias);
- free(cinfo->thishost);
- free(cinfo->host_arg);
- free(cinfo->portstr);
- free(cinfo->remhost);
- free(cinfo->remuser);
- free(cinfo->homedir);
- free(cinfo->locuser);
- free(cinfo->jmphost);
- free(cinfo);
-}
-
static int
valid_hostname(const char *s)
{
@@ -1771,8 +1751,8 @@ main(int ac, char **av)
ssh_signal(SIGCHLD, main_sigchld_handler);
/* Log into the remote system. Never returns if the login fails. */
- ssh_login(ssh, &sensitive_data, host, (struct sockaddr *)&hostaddr,
- options.port, pw, timeout_ms, cinfo);
+ ssh_login(ssh, &sensitive_data, host, &hostaddr, options.port,
+ pw, timeout_ms, cinfo);
/* We no longer need the private host keys. Clear them now. */
if (sensitive_data.nkeys != 0) {
diff --git a/sshconnect.c b/sshconnect.c
index bd077c75c..7823b6782 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -83,6 +83,49 @@ extern char *__progname;
static int show_other_keys(struct hostkeys *, struct sshkey *);
static void warn_changed_key(struct sshkey *);
+void
+ssh_conn_info_free(struct ssh_conn_info *cinfo)
+{
+ if (cinfo == NULL)
+ return;
+ free(cinfo->conn_hash_hex);
+ free(cinfo->shorthost);
+ free(cinfo->uidstr);
+ free(cinfo->keyalias);
+ free(cinfo->thishost);
+ free(cinfo->host_arg);
+ free(cinfo->portstr);
+ free(cinfo->remhost);
+ free(cinfo->remuser);
+ free(cinfo->homedir);
+ free(cinfo->locuser);
+ free(cinfo->jmphost);
+ freezero(cinfo, sizeof(*cinfo));
+}
+
+struct ssh_conn_info *
+ssh_conn_info_dup(const struct ssh_conn_info *cinfo)
+{
+ struct ssh_conn_info *ret;
+
+ if (cinfo == NULL)
+ return NULL;
+ ret = xcalloc(1, sizeof(*ret));
+ ret->conn_hash_hex = xstrdup(cinfo->conn_hash_hex);
+ ret->shorthost = xstrdup(cinfo->shorthost);
+ ret->uidstr = xstrdup(cinfo->uidstr);
+ ret->keyalias = xstrdup(cinfo->keyalias);
+ ret->thishost = xstrdup(cinfo->thishost);
+ ret->host_arg = xstrdup(cinfo->host_arg);
+ ret->portstr = xstrdup(cinfo->portstr);
+ ret->remhost = xstrdup(cinfo->remhost);
+ ret->remuser = xstrdup(cinfo->remuser);
+ ret->homedir = xstrdup(cinfo->homedir);
+ ret->locuser = xstrdup(cinfo->locuser);
+ ret->jmphost = xstrdup(cinfo->jmphost);
+ return ret;
+}
+
/* Expand a proxy command */
static char *
expand_proxy_command(const char *proxy_command, const char *user,
@@ -1559,8 +1602,8 @@ out:
*/
void
ssh_login(struct ssh *ssh, Sensitive *sensitive, const char *orighost,
- struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms,
- const struct ssh_conn_info *cinfo)
+ struct sockaddr_storage *hostaddr, u_short port, struct passwd *pw,
+ int timeout_ms, const struct ssh_conn_info *cinfo)
{
char *host;
char *server_user, *local_user;
diff --git a/sshconnect.h b/sshconnect.h
index 79d35cc19..da2a73f5a 100644
--- a/sshconnect.h
+++ b/sshconnect.h
@@ -71,7 +71,7 @@ int ssh_connect(struct ssh *, const char *, const char *,
void ssh_kill_proxy_command(void);
void ssh_login(struct ssh *, Sensitive *, const char *,
- struct sockaddr *, u_short, struct passwd *, int,
+ struct sockaddr_storage *, u_short, struct passwd *, int,
const struct ssh_conn_info *);
int verify_host_key(char *, struct sockaddr *, struct sshkey *,
@@ -80,7 +80,7 @@ int verify_host_key(char *, struct sockaddr *, struct sshkey *,
void get_hostfile_hostname_ipaddr(char *, struct sockaddr *, u_short,
char **, char **);
-void ssh_kex2(struct ssh *ssh, char *, struct sockaddr *, u_short,
+void ssh_kex2(struct ssh *ssh, char *, struct sockaddr_storage *, u_short,
const struct ssh_conn_info *);
void ssh_userauth2(struct ssh *ssh, const char *, const char *,
@@ -94,3 +94,6 @@ void maybe_add_key_to_agent(const char *, struct sshkey *,
void load_hostkeys_command(struct hostkeys *, const char *,
const char *, const struct ssh_conn_info *,
const struct sshkey *, const char *);
+
+void ssh_conn_info_free(struct ssh_conn_info *);
+struct ssh_conn_info *ssh_conn_info_dup(const struct ssh_conn_info *);
diff --git a/sshconnect2.c b/sshconnect2.c
index a296c9b8c..9efb3da8a 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -89,7 +89,7 @@ extern Options options;
*/
static char *xxx_host;
-static struct sockaddr *xxx_hostaddr;
+static struct sockaddr_storage xxx_hostaddr;
static const struct ssh_conn_info *xxx_conn_info;
static int key_type_allowed(struct sshkey *, const char *);
@@ -105,7 +105,7 @@ verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh)
fatal("Server host key %s not in HostKeyAlgorithms",
sshkey_ssh_name(hostkey));
}
- if (verify_host_key(xxx_host, xxx_hostaddr, hostkey,
+ if (verify_host_key(xxx_host, (struct sockaddr *)&xxx_hostaddr, hostkey,
xxx_conn_info) != 0)
fatal("Host key verification failed.");
return 0;
@@ -222,16 +222,16 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port,
}
void
-ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port,
- const struct ssh_conn_info *cinfo)
+ssh_kex2(struct ssh *ssh, char *host, struct sockaddr_storage *hostaddr,
+ u_short port, const struct ssh_conn_info *cinfo)
{
char *myproposal[PROPOSAL_MAX];
char *s, *all_key, *hkalgs = NULL;
int r, use_known_hosts_order = 0;
- xxx_host = host;
- xxx_hostaddr = hostaddr;
- xxx_conn_info = cinfo;
+ xxx_host = xstrdup(host);
+ xxx_hostaddr = *hostaddr;
+ xxx_conn_info = ssh_conn_info_dup(cinfo);
if (options.rekey_limit || options.rekey_interval)
ssh_packet_set_rekey_limits(ssh, options.rekey_limit,
@@ -257,8 +257,10 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port,
if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL)
fatal_f("kex_names_cat");
- if (use_known_hosts_order)
- hkalgs = order_hostkeyalgs(host, hostaddr, port, cinfo);
+ if (use_known_hosts_order) {
+ hkalgs = order_hostkeyalgs(host, (struct sockaddr *)hostaddr,
+ port, cinfo);
+ }
kex_proposal_populate_entries(ssh, myproposal, s, options.ciphers,
options.macs, compression_alg_list(options.compression),
@@ -42,6 +42,7 @@ SRC_URI = "http://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-${PV}.tar
file://CVE-2026-59996.patch \
file://CVE-2026-59995.patch \
file://CVE-2026-60001.patch \
file://CVE-2026-60002.patch \
"
SRC_URI[sha256sum] = "910211c07255a8c5ad654391b40ee59800710dd8119dd5362de09385aa7a777c"