Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5a11d4d0 authored by Ian Kent's avatar Ian Kent Committed by Linus Torvalds
Browse files

autofs4: fix waitq locking



The autofs4_catatonic_mode() function accesses the wait queue without any
locking but can be called at any time.  This could lead to a possible
double free of the name field of the wait and a double fput of the daemon
communication pipe or an fput of a NULL file pointer.

Signed-off-by: default avatarIan Kent <raven@themaw.net>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 70b52a0a
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -163,8 +163,8 @@ void autofs4_kill_sb(struct super_block *sb)
	if (!sbi)
		goto out_kill_sb;

	if (!sbi->catatonic)
		autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */
	/* Free wait queues, close pipe */
	autofs4_catatonic_mode(sbi);

	/* Clean up and release dangling references */
	autofs4_force_release(sbi);
+12 −11
Original line number Diff line number Diff line
@@ -28,6 +28,12 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi)
{
	struct autofs_wait_queue *wq, *nwq;

	mutex_lock(&sbi->wq_mutex);
	if (sbi->catatonic) {
		mutex_unlock(&sbi->wq_mutex);
		return;
	}

	DPRINTK("entering catatonic mode");

	sbi->catatonic = 1;
@@ -45,6 +51,8 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi)
	}
	fput(sbi->pipe);	/* Close the pipe */
	sbi->pipe = NULL;
	sbi->pipefd = -1;
	mutex_unlock(&sbi->wq_mutex);
}

static int autofs4_write(struct file *file, const void *addr, int bytes)
@@ -333,17 +341,10 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
			wq->name.name, notify);
	}

	/* wq->name is NULL if and only if the lock is already released */

	if (sbi->catatonic) {
		/* We might have slept, so check again for catatonic mode */
		wq->status = -ENOENT;
		if (wq->name.name) {
			kfree(wq->name.name);
			wq->name.name = NULL;
		}
	}

	/*
	 * wq->name.name is NULL iff the lock is already released
	 * or the mount has been made catatonic.
	 */
	if (wq->name.name) {
		/* Block all but "shutdown" signals while waiting */
		sigset_t oldset;