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

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
...@@ -163,8 +163,8 @@ void autofs4_kill_sb(struct super_block *sb) ...@@ -163,8 +163,8 @@ void autofs4_kill_sb(struct super_block *sb)
if (!sbi) if (!sbi)
goto out_kill_sb; goto out_kill_sb;
if (!sbi->catatonic) /* Free wait queues, close pipe */
autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */ autofs4_catatonic_mode(sbi);
/* Clean up and release dangling references */ /* Clean up and release dangling references */
autofs4_force_release(sbi); autofs4_force_release(sbi);
......
...@@ -28,6 +28,12 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi) ...@@ -28,6 +28,12 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi)
{ {
struct autofs_wait_queue *wq, *nwq; struct autofs_wait_queue *wq, *nwq;
mutex_lock(&sbi->wq_mutex);
if (sbi->catatonic) {
mutex_unlock(&sbi->wq_mutex);
return;
}
DPRINTK("entering catatonic mode"); DPRINTK("entering catatonic mode");
sbi->catatonic = 1; sbi->catatonic = 1;
...@@ -45,6 +51,8 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi) ...@@ -45,6 +51,8 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi)
} }
fput(sbi->pipe); /* Close the pipe */ fput(sbi->pipe); /* Close the pipe */
sbi->pipe = NULL; sbi->pipe = NULL;
sbi->pipefd = -1;
mutex_unlock(&sbi->wq_mutex);
} }
static int autofs4_write(struct file *file, const void *addr, int bytes) 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, ...@@ -333,17 +341,10 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
wq->name.name, notify); wq->name.name, notify);
} }
/* wq->name is NULL if and only if the lock is already released */ /*
* wq->name.name is NULL iff the lock is already released
if (sbi->catatonic) { * or the mount has been made 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;
}
}
if (wq->name.name) { if (wq->name.name) {
/* Block all but "shutdown" signals while waiting */ /* Block all but "shutdown" signals while waiting */
sigset_t oldset; sigset_t oldset;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment