summaryrefslogtreecommitdiffstats
path: root/src/providers/data_provider_fo.c
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2012-09-12 19:23:48 +0200
committerJakub Hrozek <jhrozek@redhat.com>2012-10-03 13:44:13 +0200
commit052684f1ab1c8a4fcfb2c9057c33273acbaf660e (patch)
tree9cbb6c5004e16f90188b5495204b2ce0773453ab /src/providers/data_provider_fo.c
parentb196e1e91ec04ca5af93bfd2dcfc5225f4858a54 (diff)
downloadsssd-052684f1ab1c8a4fcfb2c9057c33273acbaf660e.tar.gz
sssd-052684f1ab1c8a4fcfb2c9057c33273acbaf660e.tar.xz
sssd-052684f1ab1c8a4fcfb2c9057c33273acbaf660e.zip
FO: Check server validity before setting statussssd-1_8_5
The list of resolved servers is allocated on the back end context and kept in the fo_service structure. However, a single request often resolves a server and keeps a pointer until the end of a request and only then gives feedback about the server based on the request result. This presents a big race condition in case the SRV resolution is used. When there are requests coming in in parallel, it is possible that an incoming request will invalidate a server until another request that holds a pointer to the original server is able to give a feedback. This patch simply checks if a server is in the list of servers maintained by a service before reading its status. https://fedorahosted.org/sssd/ticket/1364
Diffstat (limited to 'src/providers/data_provider_fo.c')
-rw-r--r--src/providers/data_provider_fo.c27
1 files changed, 13 insertions, 14 deletions
diff --git a/src/providers/data_provider_fo.c b/src/providers/data_provider_fo.c
index ada41a3ac..f4627f32e 100644
--- a/src/providers/data_provider_fo.c
+++ b/src/providers/data_provider_fo.c
@@ -547,32 +547,31 @@ void reset_fo(struct be_ctx *be_ctx)
}
void be_fo_set_port_status(struct be_ctx *ctx,
+ const char *service_name,
struct fo_server *server,
enum port_status status)
{
- struct be_svc_data *svc;
- struct fo_service *fsvc;
-
- fo_set_port_status(server, status);
+ struct be_svc_data *be_svc;
- fsvc = fo_get_server_service(server);
- if (!fsvc) {
- DEBUG(SSSDBG_OP_FAILURE, ("BUG: No service associated with server\n"));
+ be_svc = be_fo_find_svc_data(ctx, service_name);
+ if (be_svc == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("No service associated with name %s\n", service_name));
return;
}
- DLIST_FOR_EACH(svc, ctx->be_fo->svcs) {
- if (svc->fo_service == fsvc) break;
- }
-
- if (!svc) {
- DEBUG(SSSDBG_OP_FAILURE, ("BUG: Unknown service\n"));
+ if (!fo_svc_has_server(be_svc->fo_service, server)) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("The server %p is not valid anymore, cannot set its status\n"));
return;
}
+ /* Now we know that the server is valid */
+ fo_set_port_status(server, status);
+
if (status == PORT_WORKING) {
/* We were successful in connecting to the server. Cycle through all
* available servers next time */
- svc->first_resolved = NULL;
+ be_svc->first_resolved = NULL;
}
}