Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 130701790bf2d95e902edf16031ff596 > files > 42

autofs-5.0.1-0.rc2.164.el5_8.src.rpm

autofs-5.0.1 - 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.1.orig/daemon/direct.c
+++ autofs-5.0.1/daemon/direct.c
@@ -1002,56 +1002,54 @@ static void expire_mutex_unlock(void *ar
 static void *do_expire_direct(void *arg)
 {
 	struct ioctl_ops *ops = get_ioctl_ops();
-	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)
 		ops->send_fail(ap->logopt,
-			       mt->ioctlfd, mt->wait_queue_token, -ENOENT);
+			       mt.ioctlfd, mt.wait_queue_token, -ENOENT);
 	else {
 		struct mapent *me;
-		cache_writelock(mt->mc);
-		me = cache_lookup_distinct(mt->mc, mt->name);
+		cache_writelock(mt.mc);
+		me = cache_lookup_distinct(mt.mc, mt.name);
 		me->ioctlfd = -1;
-		cache_unlock(mt->mc);
-		ops->send_ready(ap->logopt, mt->ioctlfd, mt->wait_queue_token);
-		ops->close(ap->logopt, mt->ioctlfd);
+		cache_unlock(mt.mc);
+		ops->send_ready(ap->logopt, mt.ioctlfd, mt.wait_queue_token);
+		ops->close(ap->logopt, mt.ioctlfd);
 	}
 	pthread_setcancelstate(state, NULL);
 
 	pthread_cleanup_pop(0);
-	pthread_cleanup_pop(1);
-	pthread_cleanup_pop(1);
 
 	return NULL;
 }
@@ -1173,6 +1171,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);
 
@@ -1187,6 +1187,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.1.orig/daemon/indirect.c
+++ autofs-5.0.1/daemon/indirect.c
@@ -576,42 +576,40 @@ static void expire_mutex_unlock(void *ar
 static void *do_expire_indirect(void *arg)
 {
 	struct ioctl_ops *ops = get_ioctl_ops();
-	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)
 		ops->send_fail(ap->logopt,
-			       ap->ioctlfd, mt->wait_queue_token, -status);
+			       ap->ioctlfd, mt.wait_queue_token, -status);
 	else
 		ops->send_ready(ap->logopt,
-				ap->ioctlfd, mt->wait_queue_token);
+				ap->ioctlfd, mt.wait_queue_token);
 	pthread_setcancelstate(state, NULL);
 
 	pthread_cleanup_pop(0);
-	pthread_cleanup_pop(1);
-	pthread_cleanup_pop(1);
 
 	return NULL;
 }
@@ -667,6 +665,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);
 
@@ -681,6 +681,8 @@ int handle_packet_expire_indirect(struct
 	}
 
 	pthread_cleanup_pop(1);
+	pthread_cleanup_pop(1);
+	pthread_cleanup_pop(1);
 
 	return 0;
 }