diff options
author | Andy Adamson <andros@citi.umich.edu> | 2006-03-20 13:44:26 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-20 13:44:26 -0500 |
commit | 8dc7c3115b611c00006eac3ee5b108296432aab7 (patch) | |
tree | be44c59907cbdcb6fdf46d0ad9cc140af757acfc /fs/locks.c | |
parent | 2e0af86f618c697b44e2d67dff151256c58201c4 (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.c | 21 |
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 | ||
675 | struct file_lock * | 675 | int |
676 | posix_test_lock(struct file *filp, struct file_lock *fl) | 676 | posix_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 | ||
692 | EXPORT_SYMBOL(posix_test_lock); | 697 | EXPORT_SYMBOL(posix_test_lock); |
@@ -1563,7 +1568,7 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd) | |||
1563 | */ | 1568 | */ |
1564 | int fcntl_getlk(struct file *filp, struct flock __user *l) | 1569 | int 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 | */ |
1718 | int fcntl_getlk64(struct file *filp, struct flock64 __user *l) | 1723 | int 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; |