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/lockd/svclock.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/lockd/svclock.c')
-rw-r--r-- | fs/lockd/svclock.c | 12 |
1 files changed, 5 insertions, 7 deletions
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index f5398097b84b..d683dd022e08 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
@@ -376,8 +376,6 @@ u32 | |||
376 | nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, | 376 | nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, |
377 | struct nlm_lock *conflock) | 377 | struct nlm_lock *conflock) |
378 | { | 378 | { |
379 | struct file_lock *fl; | ||
380 | |||
381 | dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n", | 379 | dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n", |
382 | file->f_file->f_dentry->d_inode->i_sb->s_id, | 380 | file->f_file->f_dentry->d_inode->i_sb->s_id, |
383 | file->f_file->f_dentry->d_inode->i_ino, | 381 | file->f_file->f_dentry->d_inode->i_ino, |
@@ -385,14 +383,14 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, | |||
385 | (long long)lock->fl.fl_start, | 383 | (long long)lock->fl.fl_start, |
386 | (long long)lock->fl.fl_end); | 384 | (long long)lock->fl.fl_end); |
387 | 385 | ||
388 | if ((fl = posix_test_lock(file->f_file, &lock->fl)) != NULL) { | 386 | if (posix_test_lock(file->f_file, &lock->fl, &conflock->fl)) { |
389 | dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n", | 387 | dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n", |
390 | fl->fl_type, (long long)fl->fl_start, | 388 | conflock->fl.fl_type, |
391 | (long long)fl->fl_end); | 389 | (long long)conflock->fl.fl_start, |
390 | (long long)conflock->fl.fl_end); | ||
392 | conflock->caller = "somehost"; /* FIXME */ | 391 | conflock->caller = "somehost"; /* FIXME */ |
393 | conflock->oh.len = 0; /* don't return OH info */ | 392 | conflock->oh.len = 0; /* don't return OH info */ |
394 | conflock->svid = fl->fl_pid; | 393 | conflock->svid = conflock->fl.fl_pid; |
395 | conflock->fl = *fl; | ||
396 | return nlm_lck_denied; | 394 | return nlm_lck_denied; |
397 | } | 395 | } |
398 | 396 | ||