aboutsummaryrefslogtreecommitdiffstats
path: root/fs/autofs4
diff options
context:
space:
mode:
authorIan Kent <raven@themaw.net>2008-07-24 00:30:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-24 13:47:32 -0400
commit5a11d4d0ee1ff284271f7265929d07ea4a1168a6 (patch)
tree4b9b76486afa5d9fc29216df069c5a557e09011a /fs/autofs4
parent70b52a0a5005ce6a0ceec56e97222437a0ba7506 (diff)
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: Ian Kent <raven@themaw.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/autofs4')
-rw-r--r--fs/autofs4/inode.c4
-rw-r--r--fs/autofs4/waitq.c23
2 files changed, 14 insertions, 13 deletions
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index e3e70994ab46..7bb3e5ba0537 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -163,8 +163,8 @@ void autofs4_kill_sb(struct super_block *sb)
163 if (!sbi) 163 if (!sbi)
164 goto out_kill_sb; 164 goto out_kill_sb;
165 165
166 if (!sbi->catatonic) 166 /* Free wait queues, close pipe */
167 autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */ 167 autofs4_catatonic_mode(sbi);
168 168
169 /* Clean up and release dangling references */ 169 /* Clean up and release dangling references */
170 autofs4_force_release(sbi); 170 autofs4_force_release(sbi);
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 5208cfb1df4e..55aac10cf328 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -28,6 +28,12 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi)
28{ 28{
29 struct autofs_wait_queue *wq, *nwq; 29 struct autofs_wait_queue *wq, *nwq;
30 30
31 mutex_lock(&sbi->wq_mutex);
32 if (sbi->catatonic) {
33 mutex_unlock(&sbi->wq_mutex);
34 return;
35 }
36
31 DPRINTK("entering catatonic mode"); 37 DPRINTK("entering catatonic mode");
32 38
33 sbi->catatonic = 1; 39 sbi->catatonic = 1;
@@ -45,6 +51,8 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi)
45 } 51 }
46 fput(sbi->pipe); /* Close the pipe */ 52 fput(sbi->pipe); /* Close the pipe */
47 sbi->pipe = NULL; 53 sbi->pipe = NULL;
54 sbi->pipefd = -1;
55 mutex_unlock(&sbi->wq_mutex);
48} 56}
49 57
50static int autofs4_write(struct file *file, const void *addr, int bytes) 58static 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 wq->name.name, notify); 341 wq->name.name, notify);
334 } 342 }
335 343
336 /* wq->name is NULL if and only if the lock is already released */ 344 /*
337 345 * wq->name.name is NULL iff the lock is already released
338 if (sbi->catatonic) { 346 * or the mount has been made catatonic.
339 /* We might have slept, so check again for catatonic mode */ 347 */
340 wq->status = -ENOENT;
341 if (wq->name.name) {
342 kfree(wq->name.name);
343 wq->name.name = NULL;
344 }
345 }
346
347 if (wq->name.name) { 348 if (wq->name.name) {
348 /* Block all but "shutdown" signals while waiting */ 349 /* Block all but "shutdown" signals while waiting */
349 sigset_t oldset; 350 sigset_t oldset;