upstream: the messaging layer between sshd-session and sshd-auth had a

maximum message size of 256KB. Some people apparently have configurations
larger than this and would hit this limit.

Worse, there was no good logging that could help diagnose what was
going wrong.

So this bumps the maximum message size to 4MB and implements an early
check (usable via the sshd -t test mode) that will report it to the
user where it is hopefully more visible.

bz3808, reported by Dmitry Belyavskiy, ok dtucker@

OpenBSD-Commit-ID: 69c303fb68cbd1a4735936835d67a71e7b57f63b
This commit is contained in:
djm@openbsd.org
2025-07-04 07:47:35 +00:00
committed by Damien Miller
parent fd10cea0f1
commit 0cf38d7446
3 changed files with 16 additions and 7 deletions

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: monitor_wrap.c,v 1.139 2025/05/05 02:40:30 djm Exp $ */ /* $OpenBSD: monitor_wrap.c,v 1.140 2025/07/04 07:47:35 djm Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org> * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -150,7 +150,7 @@ mm_request_send(int sock, enum monitor_reqtype type, struct sshbuf *m)
debug3_f("entering, type %d", type); debug3_f("entering, type %d", type);
if (mlen >= 0xffffffff) if (mlen >= MONITOR_MAX_MSGLEN)
fatal_f("bad length %zu", mlen); fatal_f("bad length %zu", mlen);
POKE_U32(buf, mlen + 1); POKE_U32(buf, mlen + 1);
buf[4] = (u_char) type; /* 1st byte of payload is mesg-type */ buf[4] = (u_char) type; /* 1st byte of payload is mesg-type */
@@ -183,7 +183,7 @@ mm_request_receive(int sock, struct sshbuf *m)
fatal_f("read: %s", strerror(errno)); fatal_f("read: %s", strerror(errno));
} }
msg_len = PEEK_U32(buf); msg_len = PEEK_U32(buf);
if (msg_len > 256 * 1024) if (msg_len > MONITOR_MAX_MSGLEN)
fatal_f("read: bad msg_len %d", msg_len); fatal_f("read: bad msg_len %d", msg_len);
sshbuf_reset(m); sshbuf_reset(m);
if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: monitor_wrap.h,v 1.51 2024/05/17 06:42:04 jsg Exp $ */ /* $OpenBSD: monitor_wrap.h,v 1.53 2025/07/04 07:47:35 djm Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@@ -28,6 +28,10 @@
#ifndef _MM_WRAP_H_ #ifndef _MM_WRAP_H_
#define _MM_WRAP_H_ #define _MM_WRAP_H_
#define MONITOR_MAX_MSGLEN (4 * 1024 * 1024)
/* The configuration has to fit in a monitor message along with other state */
#define MONITOR_MAX_CFGLEN (MONITOR_MAX_MSGLEN - (64 * 1024))
enum mm_keytype { MM_NOKEY, MM_HOSTKEY, MM_USERKEY }; enum mm_keytype { MM_NOKEY, MM_HOSTKEY, MM_USERKEY };
struct ssh; struct ssh;

11
sshd.c
View File

@@ -1,4 +1,4 @@
/* $OpenBSD: sshd.c,v 1.619 2025/05/24 06:43:37 dtucker Exp $ */ /* $OpenBSD: sshd.c,v 1.620 2025/07/04 07:47:35 djm Exp $ */
/* /*
* Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved.
* Copyright (c) 2002 Niels Provos. All rights reserved. * Copyright (c) 2002 Niels Provos. All rights reserved.
@@ -94,6 +94,7 @@
#include "addr.h" #include "addr.h"
#include "srclimit.h" #include "srclimit.h"
#include "atomicio.h" #include "atomicio.h"
#include "monitor_wrap.h"
/* Re-exec fds */ /* Re-exec fds */
#define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1)
@@ -1753,6 +1754,12 @@ main(int ac, char **av)
if (test_flag > 1) if (test_flag > 1)
print_config(&connection_info); print_config(&connection_info);
config = pack_config(cfg);
if (sshbuf_len(config) > MONITOR_MAX_CFGLEN) {
fatal("Configuration file is too large (have %zu, max %d)",
sshbuf_len(config), MONITOR_MAX_CFGLEN);
}
/* Configuration looks good, so exit if in test mode. */ /* Configuration looks good, so exit if in test mode. */
if (test_flag) if (test_flag)
exit(0); exit(0);
@@ -1830,8 +1837,6 @@ main(int ac, char **av)
/* ignore SIGPIPE */ /* ignore SIGPIPE */
ssh_signal(SIGPIPE, SIG_IGN); ssh_signal(SIGPIPE, SIG_IGN);
config = pack_config(cfg);
/* Get a connection, either from inetd or a listening TCP socket */ /* Get a connection, either from inetd or a listening TCP socket */
if (inetd_flag) { if (inetd_flag) {
/* Send configuration to ancestor sshd-session process */ /* Send configuration to ancestor sshd-session process */