SAM3: fix double free

This commit is contained in:
sehraf 2020-11-22 11:52:48 +01:00
parent c869b9757f
commit 1fa16aa6eb
No known key found for this signature in database
GPG Key ID: DF09F6EAE356B2C6
2 changed files with 51 additions and 14 deletions

View File

@ -124,7 +124,8 @@ int pqissli2psam3::net_internal_close(int fd)
// now to the actuall closing // now to the actuall closing
int ret = pqissl::net_internal_close(fd); int ret = pqissl::net_internal_close(fd);
rsAutoProxyMonitor::taskAsync(autoProxyType::I2PSAM3, autoProxyTask::closeConnection, this, mConn),
rsAutoProxyMonitor::taskAsync(autoProxyType::I2PSAM3, autoProxyTask::closeConnection, this, mConn);
// finally cleanup // finally cleanup
mConn = 0; mConn = 0;

View File

@ -76,6 +76,13 @@ bool p3I2pSam3::initialSetup(std::string &addr, uint16_t &/*port*/)
i2p::getKeyTypes(mSetting.address.publicKey, s, c); i2p::getKeyTypes(mSetting.address.publicKey, s, c);
RS_INFO("received key", s, c); RS_INFO("received key", s, c);
// sanity check
auto pub = i2p::publicKeyFromPrivate(mSetting.address.privateKey);
if (pub != mSetting.address.publicKey) {
RS_WARN("public key does not match private key! fixing ...");
mSetting.address.privateKey = pub;
}
IndicateConfigChanged(); IndicateConfigChanged();
} }
@ -482,7 +489,7 @@ bool p3I2pSam3::startSession()
stopSession(); stopSession();
} }
auto session = new Sam3Session(); auto session = (Sam3Session*)rs_malloc(sizeof (Sam3Session));
// add nick // add nick
paramsStr.append("inbound.nickname=" + nick); // leading space is already there paramsStr.append("inbound.nickname=" + nick); // leading space is already there
@ -572,7 +579,7 @@ void p3I2pSam3::stopSession()
RS_STACK_MUTEX(mLockSam3Access); RS_STACK_MUTEX(mLockSam3Access);
sam3CloseSession(mSetting.session); sam3CloseSession(mSetting.session);
delete mSetting.session; free(mSetting.session);
mSetting.session = nullptr; mSetting.session = nullptr;
mState = samStatus::samState::offline; mState = samStatus::samState::offline;
@ -687,46 +694,75 @@ void p3I2pSam3::establishConnection(taskTicket *ticket)
void p3I2pSam3::closeConnection(taskTicket *ticket) void p3I2pSam3::closeConnection(taskTicket *ticket)
{ {
Sam3Connection *con = static_cast<Sam3Connection*>(ticket->data); Sam3Connection *conn = static_cast<Sam3Connection*>(ticket->data);
if (mState == samStatus::samState::offline || !mSetting.session) { if (mState == samStatus::samState::offline || !mSetting.session) {
// no session found, sam was likel stopped // no session found, sam was likely stopped
RS_DBG2("no session found");
auto it = std::find(mInvalidConnections.begin(), mInvalidConnections.end(), conn);
if (it != mInvalidConnections.end()) {
// this is the expected case
mInvalidConnections.erase(it);
} else {
// this is unexpected but not a big deal, just warn
RS_WARN("cannot find connection in mInvalidConnections");
it = std::find(mValidConnections.begin(), mValidConnections.end(), conn);
if (it != mValidConnections.end()) {
mValidConnections.erase(it);
// now it is getting even weirder, still not a big deal, just warn
RS_WARN("found connection in mValidConnections");
}
}
// when libsam3 has already handled closing of the connection - which should be the case here - the memory has been freed already (-> pointer is invalid)
conn = nullptr;
} else { } else {
RS_STACK_MUTEX(mLock); RS_STACK_MUTEX(mLock);
bool callClose = true; bool callClose = true;
// search in current connections // search in current connections
auto it = std::find(mValidConnections.begin(), mValidConnections.end(), con); auto it = std::find(mValidConnections.begin(), mValidConnections.end(), conn);
if (it != mValidConnections.end()) { if (it != mValidConnections.end()) {
RS_DBG2("found valid connection");
mValidConnections.erase(it); mValidConnections.erase(it);
} else { } else {
// search in old connections // search in old connections
it = std::find(mInvalidConnections.begin(), mInvalidConnections.end(), con); it = std::find(mInvalidConnections.begin(), mInvalidConnections.end(), conn);
if (it != mInvalidConnections.end()) { if (it != mInvalidConnections.end()) {
// old connection, just ignore. *should* be freed already // old connection, just ignore. *should* be freed already
mInvalidConnections.erase(it);
RS_DBG2("found old (invalid) connection");
callClose = false; callClose = false;
con = nullptr; conn = nullptr;
} else { } else {
// weird // weird
RS_WARN("could'n find connection!"); RS_WARN("could'n find connection!");
// best thing we can do here // best thing we can do here
callClose = false; callClose = false;
con = nullptr; conn = nullptr;
} }
} }
if (callClose) { if (callClose) {
RS_DBG2("closing connection");
RS_STACK_MUTEX(mLockSam3Access); RS_STACK_MUTEX(mLockSam3Access);
sam3CloseConnection(con); sam3CloseConnection(conn);
con = nullptr; // freed by above call conn = nullptr; // freed by above call
} }
} }
if (con) { if (conn) {
delete con; free(conn);
con = nullptr; conn = nullptr;
} }
ticket->data = nullptr; ticket->data = nullptr;
rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok); rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok);
return; return;