Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

locks: ensure that fl_owner is always initialized properly in flock and lease codepaths

Currently, the fl_owner isn't set for flock locks. Some filesystems use
byte-range locks to simulate flock locks and there is a common idiom in
those that does:

fl->fl_owner = (fl_owner_t)filp;
fl->fl_start = 0;
fl->fl_end = OFFSET_MAX;

Since flock locks are generally "owned" by the open file description,
move this into the common flock lock setup code. The fl_start and fl_end
fields are already set appropriately, so remove the unneeded setting of
that in flock ops in those filesystems as well.

Finally, the lease code also sets the fl_owner as if they were owned by
the process and not the open file description. This is incorrect as
leases have the same ownership semantics as flock locks. Set them the
same way. The lease code doesn't actually use the fl_owner value for
anything, so this is more for consistency's sake than a bugfix.

Reported-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@poochiereds.net>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> (Staging portion)
Acked-by: J. Bruce Fields <bfields@fieldses.org>

+11 -32
+6 -11
drivers/staging/lustre/lustre/llite/file.c
··· 2691 2691 2692 2692 ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_FLOCK, 1); 2693 2693 2694 - if (file_lock->fl_flags & FL_FLOCK) { 2694 + if (file_lock->fl_flags & FL_FLOCK) 2695 2695 LASSERT((cmd == F_SETLKW) || (cmd == F_SETLK)); 2696 - /* flocks are whole-file locks */ 2697 - flock.l_flock.end = OFFSET_MAX; 2698 - /* For flocks owner is determined by the local file descriptor*/ 2699 - flock.l_flock.owner = (unsigned long)file_lock->fl_file; 2700 - } else if (file_lock->fl_flags & FL_POSIX) { 2701 - flock.l_flock.owner = (unsigned long)file_lock->fl_owner; 2702 - flock.l_flock.start = file_lock->fl_start; 2703 - flock.l_flock.end = file_lock->fl_end; 2704 - } else { 2696 + else if (!(file_lock->fl_flags & FL_POSIX)) 2705 2697 return -EINVAL; 2706 - } 2698 + 2699 + flock.l_flock.owner = (unsigned long)file_lock->fl_owner; 2707 2700 flock.l_flock.pid = file_lock->fl_pid; 2701 + flock.l_flock.start = file_lock->fl_start; 2702 + flock.l_flock.end = file_lock->fl_end; 2708 2703 2709 2704 /* Somewhat ugly workaround for svc lockd. 2710 2705 * lockd installs custom fl_lmops->lm_compare_owner that checks
-3
fs/9p/vfs_file.c
··· 352 352 invalidate_mapping_pages(&inode->i_data, 0, -1); 353 353 } 354 354 /* Convert flock to posix lock */ 355 - fl->fl_owner = (fl_owner_t)filp; 356 - fl->fl_start = 0; 357 - fl->fl_end = OFFSET_MAX; 358 355 fl->fl_flags |= FL_POSIX; 359 356 fl->fl_flags ^= FL_FLOCK; 360 357
-4
fs/afs/flock.c
··· 555 555 return -ENOLCK; 556 556 557 557 /* we're simulating flock() locks using posix locks on the server */ 558 - fl->fl_owner = (fl_owner_t) file; 559 - fl->fl_start = 0; 560 - fl->fl_end = OFFSET_MAX; 561 - 562 558 if (fl->fl_type == F_UNLCK) 563 559 return afs_do_unlk(file, fl); 564 560 return afs_do_setlk(file, fl);
+2 -8
fs/ceph/locks.c
··· 53 53 else 54 54 length = fl->fl_end - fl->fl_start + 1; 55 55 56 - if (lock_type == CEPH_LOCK_FCNTL) 57 - owner = secure_addr(fl->fl_owner); 58 - else 59 - owner = secure_addr(fl->fl_file); 56 + owner = secure_addr(fl->fl_owner); 60 57 61 58 dout("ceph_lock_message: rule: %d, op: %d, owner: %llx, pid: %llu, " 62 59 "start: %llu, length: %llu, wait: %d, type: %d", (int)lock_type, ··· 311 314 cephlock->length = cpu_to_le64(lock->fl_end - lock->fl_start + 1); 312 315 cephlock->client = cpu_to_le64(0); 313 316 cephlock->pid = cpu_to_le64((u64)lock->fl_pid); 314 - if (lock->fl_flags & FL_POSIX) 315 - cephlock->owner = cpu_to_le64(secure_addr(lock->fl_owner)); 316 - else 317 - cephlock->owner = cpu_to_le64(secure_addr(lock->fl_file)); 317 + cephlock->owner = cpu_to_le64(secure_addr(lock->fl_owner)); 318 318 319 319 switch (lock->fl_type) { 320 320 case F_RDLCK:
-1
fs/fuse/file.c
··· 2304 2304 struct fuse_file *ff = file->private_data; 2305 2305 2306 2306 /* emulate flock with POSIX locks */ 2307 - fl->fl_owner = (fl_owner_t) file; 2308 2307 ff->flock = true; 2309 2308 err = fuse_setlk(file, fl, 1); 2310 2309 }
+3 -1
fs/locks.c
··· 322 322 return -ENOMEM; 323 323 324 324 fl->fl_file = filp; 325 + fl->fl_owner = (fl_owner_t)filp; 325 326 fl->fl_pid = current->tgid; 326 327 fl->fl_flags = FL_FLOCK; 327 328 fl->fl_type = type; ··· 428 427 if (assign_type(fl, type) != 0) 429 428 return -EINVAL; 430 429 431 - fl->fl_owner = current->files; 430 + fl->fl_owner = (fl_owner_t)filp; 432 431 fl->fl_pid = current->tgid; 433 432 434 433 fl->fl_file = filp; ··· 2317 2316 2318 2317 if (filp->f_op->flock) { 2319 2318 struct file_lock fl = { 2319 + .fl_owner = (fl_owner_t)filp, 2320 2320 .fl_pid = current->tgid, 2321 2321 .fl_file = filp, 2322 2322 .fl_flags = FL_FLOCK,
-4
fs/nfs/file.c
··· 916 916 is_local = 1; 917 917 918 918 /* We're simulating flock() locks using posix locks on the server */ 919 - fl->fl_owner = (fl_owner_t)filp; 920 - fl->fl_start = 0; 921 - fl->fl_end = OFFSET_MAX; 922 - 923 919 if (fl->fl_type == F_UNLCK) 924 920 return do_unlk(filp, cmd, fl, is_local); 925 921 return do_setlk(filp, cmd, fl, is_local);