From 63dda3cf702a788990d4471393a388d565a581e0 Mon Sep 17 00:00:00 2001 From: David Gwynne Date: Fri, 15 Mar 2013 12:20:12 +0000 Subject: fix a huge bug in tftpd. there was a double free if an option ack failed. if oack fails, the client gets freed, then the oack caller tries to free the options which were just freed. found by Maxime Villard who provided a fix. unfortunately his fix still had a double free but it was pretty close. ok MALLOC_OPTIONS=S --- usr.sbin/tftpd/tftpd.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/usr.sbin/tftpd/tftpd.c b/usr.sbin/tftpd/tftpd.c index f2a0582cd37..cf5238f406e 100644 --- a/usr.sbin/tftpd/tftpd.c +++ b/usr.sbin/tftpd/tftpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tftpd.c,v 1.8 2012/07/13 02:31:46 gsoares Exp $ */ +/* $OpenBSD: tftpd.c,v 1.9 2013/03/15 12:20:11 dlg Exp $ */ /* * Copyright (c) 2012 David Gwynne @@ -168,7 +168,7 @@ void tftp_end(struct tftp_client *); void tftp(struct tftp_client *, struct tftphdr *, size_t); void tftp_open(struct tftp_client *, const char *); void nak(struct tftp_client *, int); -void oack(struct tftp_client *); +int oack(struct tftp_client *); void oack_done(int, short, void *); void sendfile(struct tftp_client *); @@ -872,11 +872,14 @@ tftp_open(struct tftp_client *client, const char *filename) int ecode; ecode = validate_access(client, filename); - if (ecode) - goto error; + if (ecode) { + nak(client, ecode); + return; + } if (client->options) { - oack(client); + if (oack(client) == -1) + return; free(client->options); client->options = NULL; @@ -886,9 +889,6 @@ tftp_open(struct tftp_client *client, const char *filename) sendfile(client); return; - -error: - nak(client, ecode); } /* @@ -1386,7 +1386,7 @@ nak(struct tftp_client *client, int error) /* * Send an oack packet (option acknowledgement). */ -void +int oack(struct tftp_client *client) { struct opt_client *options = client->options; @@ -1436,10 +1436,11 @@ oack(struct tftp_client *client) oack_done, client); event_add(&client->sev, &client->tv); - return; + return (0); error: client_free(client); + return (-1); } int -- cgit v1.2.3