summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlexander Barton <alex@barton.de>2018-03-11 21:06:03 +0100
committerAlexander Barton <alex@barton.de>2018-03-11 21:18:38 +0100
commit798de94d6556bdf2c6019f368ad7441fe6e2d1be (patch)
tree6692960b76994def202db2eb015badf157e327ab
parentac341176da5bbe99a9b07353f6e9790575ce1493 (diff)
downloadngircd-798de94d6556bdf2c6019f368ad7441fe6e2d1be.tar.gz
ngircd-798de94d6556bdf2c6019f368ad7441fe6e2d1be.zip
Fix use-after-free while handling ERROR during client login
This patch fixes a "use after free" bug which is hit while processing
ERROR commands while a new client is logging into the server, which
leads to only the CLIENT structure becoming freed, but not the
CONNECTION structure, too. And this leads to the daemon accessing the
already freed CLIENT structure later on ...

So now IRC_ERROR() uses the correct function Conn_Close() to correctly
free both structures.

The CONNECTION structure is cleaned up later on, and the freed CLIENT
structure can't be overwritten during normal operations, therefore this
bug normally can't crash (DoS) the service -- but you can easily hit it
when using the GCC option "-fsanitize=address", or run ngIRCd with
Valgrind.

Thanks a lot to Joseph Bisch <joseph.bisch@gmail.com> for discovering
and reporting this issue!
-rw-r--r--src/ngircd/irc.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/src/ngircd/irc.c b/src/ngircd/irc.c
index 12fd8214..eae046d3 100644
--- a/src/ngircd/irc.c
+++ b/src/ngircd/irc.c
@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2015 Alexander Barton (alex@barton.de) and Contributors.
+ * Copyright (c)2001-2018 Alexander Barton (alex@barton.de) and Contributors.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -112,7 +112,7 @@ IRC_ERROR(CLIENT *Client, REQUEST *Req)
 	}
 
 	if (Client_Conn(Client) != NONE) {
-		Client_Destroy(Client, NULL, msg, false);
+		Conn_Close(Client_Conn(Client), NULL, msg, false);
 		return DISCONNECTED;
 	}