mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 11:41:38 -04:00
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 <[email protected]> Signed-off-by: J. Bruce Fields <[email protected]> Signed-off-by: Trond Myklebust <[email protected]>
This commit is contained in:
parent
2e0af86f61
commit
8dc7c3115b
5 changed files with 28 additions and 27 deletions
21
fs/locks.c
21
fs/locks.c
|
|
@ -672,8 +672,9 @@ static int locks_block_on_timeout(struct file_lock *blocker, struct file_lock *w
|
|||
return result;
|
||||
}
|
||||
|
||||
struct file_lock *
|
||||
posix_test_lock(struct file *filp, struct file_lock *fl)
|
||||
int
|
||||
posix_test_lock(struct file *filp, struct file_lock *fl,
|
||||
struct file_lock *conflock)
|
||||
{
|
||||
struct file_lock *cfl;
|
||||
|
||||
|
|
@ -684,9 +685,13 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
|
|||
if (posix_locks_conflict(cfl, fl))
|
||||
break;
|
||||
}
|
||||
if (cfl) {
|
||||
locks_copy_lock(conflock, cfl);
|
||||
unlock_kernel();
|
||||
return 1;
|
||||
}
|
||||
unlock_kernel();
|
||||
|
||||
return (cfl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(posix_test_lock);
|
||||
|
|
@ -1563,7 +1568,7 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd)
|
|||
*/
|
||||
int fcntl_getlk(struct file *filp, struct flock __user *l)
|
||||
{
|
||||
struct file_lock *fl, file_lock;
|
||||
struct file_lock *fl, cfl, file_lock;
|
||||
struct flock flock;
|
||||
int error;
|
||||
|
||||
|
|
@ -1587,7 +1592,7 @@ int fcntl_getlk(struct file *filp, struct flock __user *l)
|
|||
else
|
||||
fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
|
||||
} else {
|
||||
fl = posix_test_lock(filp, &file_lock);
|
||||
fl = (posix_test_lock(filp, &file_lock, &cfl) ? &cfl : NULL);
|
||||
}
|
||||
|
||||
flock.l_type = F_UNLCK;
|
||||
|
|
@ -1717,7 +1722,7 @@ out:
|
|||
*/
|
||||
int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
|
||||
{
|
||||
struct file_lock *fl, file_lock;
|
||||
struct file_lock *fl, cfl, file_lock;
|
||||
struct flock64 flock;
|
||||
int error;
|
||||
|
||||
|
|
@ -1741,7 +1746,7 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
|
|||
else
|
||||
fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
|
||||
} else {
|
||||
fl = posix_test_lock(filp, &file_lock);
|
||||
fl = (posix_test_lock(filp, &file_lock, &cfl) ? &cfl : NULL);
|
||||
}
|
||||
|
||||
flock.l_type = F_UNLCK;
|
||||
|
|
|
|||
Loading…
Reference in a new issue