aboutsummaryrefslogtreecommitdiffstats
path: root/fs/locks.c
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@citi.umich.edu>2007-10-30 11:20:02 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-30 12:04:18 -0400
commit97855b49b6bac0bd25f16b017883634d13591d00 (patch)
treee0895adabfda85bd9dc7514265940fdef8b1e506 /fs/locks.c
parentfb7267acfef1de3e49d4e0c80be3cc603e974b3b (diff)
locks: fix possible infinite loop in posix deadlock detection
It's currently possible to send posix_locks_deadlock() into an infinite loop (under the BKL). For now, fix this just by bailing out after a few iterations. We may want to fix this in a way that better clarifies the semantics of deadlock detection. But that will take more time, and this minimal fix is probably adequate for any realistic scenario, and is simple enough to be appropriate for applying to stable kernels now. Thanks to George Davis for reporting the problem. Cc: "George G. Davis" <gdavis@mvista.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> Acked-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/locks.c')
-rw-r--r--fs/locks.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/fs/locks.c b/fs/locks.c
index 0127a2846819..8b8388eca05e 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -696,17 +696,28 @@ EXPORT_SYMBOL(posix_test_lock);
696 * Note: the above assumption may not be true when handling lock requests 696 * Note: the above assumption may not be true when handling lock requests
697 * from a broken NFS client. But broken NFS clients have a lot more to 697 * from a broken NFS client. But broken NFS clients have a lot more to
698 * worry about than proper deadlock detection anyway... --okir 698 * worry about than proper deadlock detection anyway... --okir
699 *
700 * However, the failure of this assumption (also possible in the case of
701 * multiple tasks sharing the same open file table) also means there's no
702 * guarantee that the loop below will terminate. As a hack, we give up
703 * after a few iterations.
699 */ 704 */
705
706#define MAX_DEADLK_ITERATIONS 10
707
700static int posix_locks_deadlock(struct file_lock *caller_fl, 708static int posix_locks_deadlock(struct file_lock *caller_fl,
701 struct file_lock *block_fl) 709 struct file_lock *block_fl)
702{ 710{
703 struct file_lock *fl; 711 struct file_lock *fl;
712 int i = 0;
704 713
705next_task: 714next_task:
706 if (posix_same_owner(caller_fl, block_fl)) 715 if (posix_same_owner(caller_fl, block_fl))
707 return 1; 716 return 1;
708 list_for_each_entry(fl, &blocked_list, fl_link) { 717 list_for_each_entry(fl, &blocked_list, fl_link) {
709 if (posix_same_owner(fl, block_fl)) { 718 if (posix_same_owner(fl, block_fl)) {
719 if (i++ > MAX_DEADLK_ITERATIONS)
720 return 0;
710 fl = fl->fl_next; 721 fl = fl->fl_next;
711 block_fl = fl; 722 block_fl = fl;
712 goto next_task; 723 goto next_task;