[openssh-commits] [openssh] 02/02: upstream: make writing known_hosts lines more atomic, by writing

git+noreply at mindrot.org git+noreply at mindrot.org
Wed Apr 30 15:27:03 AEST 2025


This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

commit e048230106fb3f5e7cc07abc311c6feb5f52fd05
Author: djm at openbsd.org <djm at openbsd.org>
AuthorDate: Wed Apr 30 05:26:15 2025 +0000

    upstream: make writing known_hosts lines more atomic, by writing
    
    the entire line in one operation and using unbuffered stdio.
    
    Usually writes to this file are serialised on the "Are you sure you
    want to continue connecting?" prompt, but if host key checking is
    disabled and connections were being made with high concurrency
    then interleaved writes might have been possible.
    
    feedback/ok deraadt@ millert@
    
    OpenBSD-Commit-ID: d11222b49dabe5cfe0937b49cb439ba3d4847b08
---
 hostfile.c | 52 ++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 40 insertions(+), 12 deletions(-)

diff --git a/hostfile.c b/hostfile.c
index a4a5a9a5e..e941fc450 100644
--- a/hostfile.c
+++ b/hostfile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hostfile.c,v 1.96 2025/04/30 05:23:15 djm Exp $ */
+/* $OpenBSD: hostfile.c,v 1.97 2025/04/30 05:26:15 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -434,7 +434,7 @@ lookup_marker_in_hostkeys(struct hostkeys *hostkeys, int want_marker)
 }
 
 static int
-write_host_entry(FILE *f, const char *host, const char *ip,
+format_host_entry(struct sshbuf *entry, const char *host, const char *ip,
     const struct sshkey *key, int store_hash)
 {
 	int r, success = 0;
@@ -449,22 +449,50 @@ write_host_entry(FILE *f, const char *host, const char *ip,
 			free(lhost);
 			return 0;
 		}
-		fprintf(f, "%s ", hashed_host);
-	} else if (ip != NULL)
-		fprintf(f, "%s,%s ", lhost, ip);
-	else {
-		fprintf(f, "%s ", lhost);
+		if ((r = sshbuf_putf(entry, "%s ", hashed_host)) != 0)
+			fatal_fr(r, "sshbuf_putf");
+	} else if (ip != NULL) {
+		if ((r = sshbuf_putf(entry, "%s,%s ", lhost, ip)) != 0)
+			fatal_fr(r, "sshbuf_putf");
+	} else {
+		if ((r = sshbuf_putf(entry, "%s ", lhost)) != 0)
+			fatal_fr(r, "sshbuf_putf");
 	}
 	free(hashed_host);
 	free(lhost);
-	if ((r = sshkey_write(key, f)) == 0)
+	if ((r = sshkey_format_text(key, entry)) == 0)
 		success = 1;
 	else
 		error_fr(r, "sshkey_write");
-	fputc('\n', f);
+	if ((r = sshbuf_putf(entry, "\n")) != 0)
+		fatal_fr(r, "sshbuf_putf");
+
 	/* If hashing is enabled, the IP address needs to go on its own line */
 	if (success && store_hash && ip != NULL)
-		success = write_host_entry(f, ip, NULL, key, 1);
+		success = format_host_entry(entry, ip, NULL, key, 1);
+	return success;
+}
+
+static int
+write_host_entry(FILE *f, const char *host, const char *ip,
+    const struct sshkey *key, int store_hash)
+{
+	int r, success = 0;
+	struct sshbuf *entry = NULL;
+
+	if ((entry = sshbuf_new()) == NULL)
+		fatal_f("allocation failed");
+	if ((r = format_host_entry(entry, host, ip, key, store_hash)) != 1) {
+		debug_f("failed to format host entry");
+		goto out;
+	}
+	if ((r = fwrite(sshbuf_ptr(entry), sshbuf_len(entry), 1, f)) != 1) {
+		error_f("fwrite: %s", strerror(errno));
+		goto out;
+	}
+	success = 1;
+ out:
+	sshbuf_free(entry);
 	return success;
 }
 
@@ -520,9 +548,9 @@ add_host_to_hostfile(const char *filename, const char *host,
 	if (key == NULL)
 		return 1;	/* XXX ? */
 	hostfile_create_user_ssh_dir(filename, 0);
-	f = fopen(filename, "a+");
-	if (!f)
+	if ((f = fopen(filename, "a+")) == NULL)
 		return 0;
+	setvbuf(f, NULL, _IONBF, 0);
 	/* Make sure we have a terminating newline. */
 	if (fseek(f, -1L, SEEK_END) == 0 && fgetc(f) != '\n')
 		addnl = 1;

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list