autofs-5.0.3 - fix incorrect pthreads condition handling for expire requests.
From: Ian Kent <raven@themaw.net>
Occassionally, when starting an expire thread we can attempt to use the
structure for parameter communication after it has been freed. This patch
resolves this issue.
---
daemon/direct.c | 40 +++++++++++++++++++++-------------------
daemon/indirect.c | 28 +++++++++++++++-------------
2 files changed, 36 insertions(+), 32 deletions(-)
--- autofs-5.0.3.orig/daemon/direct.c
+++ autofs-5.0.3/daemon/direct.c
@@ -1033,55 +1033,53 @@ static void expire_mutex_unlock(void *ar
static void *do_expire_direct(void *arg)
{
- struct pending_args *mt;
+ struct pending_args *args, mt;
struct autofs_point *ap;
size_t len;
int status, state;
- mt = (struct pending_args *) arg;
+ args = (struct pending_args *) arg;
status = pthread_mutex_lock(&ea_mutex);
if (status)
fatal(status);
- ap = mt->ap;
+ memcpy(&mt, args, sizeof(struct pending_args));
+
+ ap = mt.ap;
- mt->signaled = 1;
- status = pthread_cond_signal(&mt->cond);
+ args->signaled = 1;
+ status = pthread_cond_signal(&args->cond);
if (status)
fatal(status);
expire_mutex_unlock(NULL);
- pthread_cleanup_push(free_pending_args, mt);
- pthread_cleanup_push(pending_cond_destroy, mt);
- pthread_cleanup_push(expire_send_fail, mt);
+ pthread_cleanup_push(expire_send_fail, &mt);
- len = _strlen(mt->name, KEY_MAX_LEN);
+ len = _strlen(mt.name, KEY_MAX_LEN);
if (!len) {
- warn(ap->logopt, "direct key path too long %s", mt->name);
+ warn(ap->logopt, "direct key path too long %s", mt.name);
/* TODO: force umount ?? */
pthread_exit(NULL);
}
- status = do_expire(ap, mt->name, len);
+ status = do_expire(ap, mt.name, len);
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
if (status)
- send_fail(ap->logopt, mt->ioctlfd, mt->wait_queue_token);
+ send_fail(ap->logopt, mt.ioctlfd, mt.wait_queue_token);
else {
struct mapent *me;
- cache_readlock(mt->mc);
- me = cache_lookup_distinct(mt->mc, mt->name);
+ cache_readlock(mt.mc);
+ me = cache_lookup_distinct(mt.mc, mt.name);
me->ioctlfd = -1;
- cache_unlock(mt->mc);
- send_ready(ap->logopt, mt->ioctlfd, mt->wait_queue_token);
- close(mt->ioctlfd);
+ cache_unlock(mt.mc);
+ send_ready(ap->logopt, mt.ioctlfd, mt.wait_queue_token);
+ close(mt.ioctlfd);
}
pthread_setcancelstate(state, NULL);
pthread_cleanup_pop(0);
- pthread_cleanup_pop(1);
- pthread_cleanup_pop(1);
return NULL;
}
@@ -1198,6 +1196,8 @@ int handle_packet_expire_direct(struct a
cache_unlock(mc);
master_source_unlock(ap->entry);
+ pthread_cleanup_push(free_pending_args, mt);
+ pthread_cleanup_push(pending_cond_destroy, mt);
pthread_cleanup_push(expire_mutex_unlock, NULL);
pthread_setcancelstate(state, NULL);
@@ -1212,6 +1212,8 @@ int handle_packet_expire_direct(struct a
}
pthread_cleanup_pop(1);
+ pthread_cleanup_pop(1);
+ pthread_cleanup_pop(1);
return 0;
}
--- autofs-5.0.3.orig/daemon/indirect.c
+++ autofs-5.0.3/daemon/indirect.c
@@ -596,40 +596,38 @@ static void expire_mutex_unlock(void *ar
static void *do_expire_indirect(void *arg)
{
- struct pending_args *mt;
+ struct pending_args *args, mt;
struct autofs_point *ap;
int status, state;
- mt = (struct pending_args *) arg;
+ args = (struct pending_args *) arg;
status = pthread_mutex_lock(&ea_mutex);
if (status)
fatal(status);
- ap = mt->ap;
+ memcpy(&mt, args, sizeof(struct pending_args));
- mt->signaled = 1;
- status = pthread_cond_signal(&mt->cond);
+ ap = mt.ap;
+
+ args->signaled = 1;
+ status = pthread_cond_signal(&args->cond);
if (status)
fatal(status);
expire_mutex_unlock(NULL);
- pthread_cleanup_push(free_pending_args, mt);
- pthread_cleanup_push(pending_cond_destroy, mt);
- pthread_cleanup_push(expire_send_fail, mt);
+ pthread_cleanup_push(expire_send_fail, &mt);
- status = do_expire(mt->ap, mt->name, mt->len);
+ status = do_expire(mt.ap, mt.name, mt.len);
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
if (status)
- send_fail(ap->logopt, ap->ioctlfd, mt->wait_queue_token);
+ send_fail(ap->logopt, ap->ioctlfd, mt.wait_queue_token);
else
- send_ready(ap->logopt, ap->ioctlfd, mt->wait_queue_token);
+ send_ready(ap->logopt, ap->ioctlfd, mt.wait_queue_token);
pthread_setcancelstate(state, NULL);
pthread_cleanup_pop(0);
- pthread_cleanup_pop(1);
- pthread_cleanup_pop(1);
return NULL;
}
@@ -682,6 +680,8 @@ int handle_packet_expire_indirect(struct
return 1;
}
+ pthread_cleanup_push(free_pending_args, mt);
+ pthread_cleanup_push(pending_cond_destroy, mt);
pthread_cleanup_push(expire_mutex_unlock, NULL);
pthread_setcancelstate(state, NULL);
@@ -696,6 +696,8 @@ int handle_packet_expire_indirect(struct
}
pthread_cleanup_pop(1);
+ pthread_cleanup_pop(1);
+ pthread_cleanup_pop(1);
return 0;
}