aboutsummaryrefslogtreecommitdiffstats
path: root/fs/locks.c
diff options
context:
space:
mode:
authorAndy Adamson <andros@citi.umich.edu>2006-03-20 13:44:26 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-03-20 13:44:26 -0500
commit8dc7c3115b611c00006eac3ee5b108296432aab7 (patch)
treebe44c59907cbdcb6fdf46d0ad9cc140af757acfc /fs/locks.c
parent2e0af86f618c697b44e2d67dff151256c58201c4 (diff)
locks,lockd: fix race in nlmsvc_testlock
posix_test_lock() returns a pointer to a struct file_lock which is unprotected and can be removed while in use by the caller. Move the conflicting lock from the return to a parameter, and copy the conflicting lock. In most cases the caller ends up putting the copy of the conflicting lock on the stack. On i386, sizeof(struct file_lock) appears to be about 100 bytes. We're assuming that's reasonable. Signed-off-by: Andy Adamson <andros@citi.umich.edu> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/locks.c')
-rw-r--r--fs/locks.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/fs/locks.c b/fs/locks.c
index cb940b142c5f..231b23c12c3d 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -672,8 +672,9 @@ static int locks_block_on_timeout(struct file_lock *blocker, struct file_lock *w
672 return result; 672 return result;
673} 673}
674 674
675struct file_lock * 675int
676posix_test_lock(struct file *filp, struct file_lock *fl) 676posix_test_lock(struct file *filp, struct file_lock *fl,
677 struct file_lock *conflock)
677{ 678{
678 struct file_lock *cfl; 679 struct file_lock *cfl;
679 680
@@ -684,9 +685,13 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
684 if (posix_locks_conflict(cfl, fl)) 685 if (posix_locks_conflict(cfl, fl))
685 break; 686 break;
686 } 687 }
688 if (cfl) {
689 locks_copy_lock(conflock, cfl);
690 unlock_kernel();
691 return 1;
692 }
687 unlock_kernel(); 693 unlock_kernel();
688 694 return 0;
689 return (cfl);
690} 695}
691 696
692EXPORT_SYMBOL(posix_test_lock); 697EXPORT_SYMBOL(posix_test_lock);
@@ -1563,7 +1568,7 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd)
1563 */ 1568 */
1564int fcntl_getlk(struct file *filp, struct flock __user *l) 1569int fcntl_getlk(struct file *filp, struct flock __user *l)
1565{ 1570{
1566 struct file_lock *fl, file_lock; 1571 struct file_lock *fl, cfl, file_lock;
1567 struct flock flock; 1572 struct flock flock;
1568 int error; 1573 int error;
1569 1574
@@ -1587,7 +1592,7 @@ int fcntl_getlk(struct file *filp, struct flock __user *l)
1587 else 1592 else
1588 fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock); 1593 fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
1589 } else { 1594 } else {
1590 fl = posix_test_lock(filp, &file_lock); 1595 fl = (posix_test_lock(filp, &file_lock, &cfl) ? &cfl : NULL);
1591 } 1596 }
1592 1597
1593 flock.l_type = F_UNLCK; 1598 flock.l_type = F_UNLCK;
@@ -1717,7 +1722,7 @@ out:
1717 */ 1722 */
1718int fcntl_getlk64(struct file *filp, struct flock64 __user *l) 1723int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
1719{ 1724{
1720 struct file_lock *fl, file_lock; 1725 struct file_lock *fl, cfl, file_lock;
1721 struct flock64 flock; 1726 struct flock64 flock;
1722 int error; 1727 int error;
1723 1728
@@ -1741,7 +1746,7 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
1741 else 1746 else
1742 fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock); 1747 fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
1743 } else { 1748 } else {
1744 fl = posix_test_lock(filp, &file_lock); 1749 fl = (posix_test_lock(filp, &file_lock, &cfl) ? &cfl : NULL);
1745 } 1750 }
1746 1751
1747 flock.l_type = F_UNLCK; 1752 flock.l_type = F_UNLCK;