summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Březina <pbrezina@redhat.com>2017-10-19 10:39:21 +0200
committerPavel Březina <pbrezina@redhat.com>2017-10-31 10:48:55 +0100
commite5ca30a04151e9b597363f4e1234674f96349706 (patch)
tree275c25cfb5460365d2434bd5a3cb97aed3f15483
parent1185cbce8d5dd04e539ca74d8f9564e5715a78aa (diff)
downloadsssd-sudo.tar.gz
sssd-sudo.tar.xz
sssd-sudo.zip
sudo: always use srv_opts from id contextsudo
Prior this patch, we remember id_ctx->srv_opts in sudo request to switch the latest usn values. This works fine most of the time but it may cause a crash. If we have two concurrent sudo refresh and one of these fails, it causes failover to try the next server and possibly replacing the old srv_opts with new one and it causes an access after free in the other refresh.
-rw-r--r--src/providers/ldap/sdap_async_sudo.c7
1 files changed, 1 insertions, 6 deletions
diff --git a/src/providers/ldap/sdap_async_sudo.c b/src/providers/ldap/sdap_async_sudo.c
index 3c69837fd..88a387422 100644
--- a/src/providers/ldap/sdap_async_sudo.c
+++ b/src/providers/ldap/sdap_async_sudo.c
@@ -279,7 +279,6 @@ done:
struct sdap_sudo_refresh_state {
struct sdap_sudo_ctx *sudo_ctx;
struct tevent_context *ev;
- struct sdap_server_opts *srv_opts;
struct sdap_options *opts;
struct sdap_id_op *sdap_op;
struct sysdb_ctx *sysdb;
@@ -405,9 +404,6 @@ static void sdap_sudo_refresh_connect_done(struct tevent_req *subreq)
DEBUG(SSSDBG_TRACE_FUNC, "SUDO LDAP connection successful\n");
- /* Obtain srv_opts here in case of first connection. */
- state->srv_opts = state->sudo_ctx->id_ctx->srv_opts;
-
/* Renew host information if needed. */
if (state->sudo_ctx->run_hostinfo) {
subreq = sdap_sudo_get_hostinfo_send(state, state->opts,
@@ -586,7 +582,6 @@ static void sdap_sudo_refresh_done(struct tevent_req *subreq)
goto done;
}
-
/* start transaction */
ret = sysdb_transaction_start(state->sysdb);
if (ret != EOK) {
@@ -621,7 +616,7 @@ static void sdap_sudo_refresh_done(struct tevent_req *subreq)
/* remember new usn */
ret = sysdb_get_highest_usn(state, rules, rules_count, &usn);
if (ret == EOK) {
- sdap_sudo_set_usn(state->srv_opts, usn);
+ sdap_sudo_set_usn(state->sudo_ctx->id_ctx->srv_opts, usn);
} else {
DEBUG(SSSDBG_MINOR_FAILURE, "Unable to get highest USN [%d]: %s\n",
ret, sss_strerror(ret));