diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-10-18 17:20:16 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-10-18 17:20:16 -0400 |
commit | 039c4d7a82d8268ec71f59679460b41d0dd9b225 (patch) | |
tree | a2f76afdda97f92df432b5d04e335ee90c42ced6 /fs | |
parent | 06735b3454824bd561decbde46111f144e905923 (diff) |
NFS: Fix up a race in the NFS implementation of GETLK
...and fix a memory corruption bug due to improper use of memcpy() on
a struct file_lock.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/file.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 6bdcfa95de94..572d8593486f 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -376,22 +376,31 @@ out_swapfile: | |||
376 | 376 | ||
377 | static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) | 377 | static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) |
378 | { | 378 | { |
379 | struct file_lock *cfl; | ||
379 | struct inode *inode = filp->f_mapping->host; | 380 | struct inode *inode = filp->f_mapping->host; |
380 | int status = 0; | 381 | int status = 0; |
381 | 382 | ||
382 | lock_kernel(); | 383 | lock_kernel(); |
383 | /* Use local locking if mounted with "-onolock" */ | 384 | /* Try local locking first */ |
384 | if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) | 385 | cfl = posix_test_lock(filp, fl); |
385 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 386 | if (cfl != NULL) { |
386 | else { | 387 | locks_copy_lock(fl, cfl); |
387 | struct file_lock *cfl = posix_test_lock(filp, fl); | 388 | goto out; |
388 | |||
389 | fl->fl_type = F_UNLCK; | ||
390 | if (cfl != NULL) | ||
391 | memcpy(fl, cfl, sizeof(*fl)); | ||
392 | } | 389 | } |
390 | |||
391 | if (nfs_have_delegation(inode, FMODE_READ)) | ||
392 | goto out_noconflict; | ||
393 | |||
394 | if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM) | ||
395 | goto out_noconflict; | ||
396 | |||
397 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | ||
398 | out: | ||
393 | unlock_kernel(); | 399 | unlock_kernel(); |
394 | return status; | 400 | return status; |
401 | out_noconflict: | ||
402 | fl->fl_type = F_UNLCK; | ||
403 | goto out; | ||
395 | } | 404 | } |
396 | 405 | ||
397 | static int do_vfs_lock(struct file *file, struct file_lock *fl) | 406 | static int do_vfs_lock(struct file *file, struct file_lock *fl) |