diff options
author | Stefan Metzmacher <metze@samba.org> | 2011-11-10 14:43:55 +0100 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2011-11-10 16:31:59 +0100 |
commit | 17f1a97a614db4ed8292544988cb6a6cf56621d8 (patch) | |
tree | afdd7b001bc6ea8efd59956b90a38b0328e625db /libcli/cldap | |
parent | 88bcdbb16a42dcd21bb1584d7d7ffa00ac1957b8 (diff) | |
download | samba-17f1a97a614db4ed8292544988cb6a6cf56621d8.tar.gz samba-17f1a97a614db4ed8292544988cb6a6cf56621d8.tar.bz2 samba-17f1a97a614db4ed8292544988cb6a6cf56621d8.zip |
libcli/cldap: fix a crash bug in cldap_socket_recv_dgram() (bug #8593)
After a calling any wrapper of tevent_req_notify_callback(),
e.g. tevent_req_nterror(), tevent_req_done(), tevent_req_nomem(),
a function has to return immediately otherwise it is very likely to
crash, unless in calls tevent_req_defer_callback() before.
metze
Autobuild-User: Stefan Metzmacher <metze@samba.org>
Autobuild-Date: Thu Nov 10 16:31:59 CET 2011 on sn-devel-104
Diffstat (limited to 'libcli/cldap')
-rw-r--r-- | libcli/cldap/cldap.c | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/libcli/cldap/cldap.c b/libcli/cldap/cldap.c index b7df9d2283..29c3b7bb51 100644 --- a/libcli/cldap/cldap.c +++ b/libcli/cldap/cldap.c @@ -258,7 +258,8 @@ static bool cldap_socket_recv_dgram(struct cldap_socket *c, p = idr_find(c->searches.idr, in->ldap_msg->messageid); if (p == NULL) { if (!c->incoming.handler) { - goto done; + TALLOC_FREE(in); + return true; } /* this function should free or steal 'in' */ @@ -266,37 +267,51 @@ static bool cldap_socket_recv_dgram(struct cldap_socket *c, return false; } - search = talloc_get_type(p, struct cldap_search_state); + search = talloc_get_type_abort(p, struct cldap_search_state); search->response.in = talloc_move(search, &in); search->response.asn1 = asn1; search->response.asn1->ofs = 0; DLIST_REMOVE(c->searches.list, search); - if (!cldap_recvfrom_setup(c)) { - goto nomem; + if (cldap_recvfrom_setup(c)) { + tevent_req_done(search->req); + return true; } + /* + * This request was ok, just defer the notify of the caller + * and then just fail the next request if needed + */ + tevent_req_defer_callback(search->req, search->caller.ev); tevent_req_done(search->req); - talloc_free(in); - return true; + status = NT_STATUS_NO_MEMORY; + /* in is NULL it this point */ + goto nterror; nomem: in->recv_errno = ENOMEM; error: status = map_nt_error_from_unix_common(in->recv_errno); nterror: + TALLOC_FREE(in); /* in connected mode the first pending search gets the error */ if (!c->connected) { /* otherwise we just ignore the error */ - goto done; + return false; } if (!c->searches.list) { - goto done; + return false; } + /* + * We might called tevent_req_done() for a successful + * search before, so we better deliver the failure + * after the success, that is why we better also + * use tevent_req_defer_callback() here. + */ + tevent_req_defer_callback(c->searches.list->req, + c->searches.list->caller.ev); tevent_req_nterror(c->searches.list->req, status); -done: - talloc_free(in); return false; } |