]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
locks: prevent side-effects of locks_release_private before file_lock is initialized
authorFilipe Brandenburger <filbranden@gmail.com>
Fri, 27 Jul 2012 04:42:52 +0000 (00:42 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Fri, 27 Jul 2012 13:39:55 +0000 (09:39 -0400)
When calling fcntl(fd, F_SETLEASE, lck) [with lck=F_WRLCK or F_RDLCK],
the custom signal or owner (if any were previously set using F_SETSIG
or F_SETOWN fcntls) would be reset when F_SETLEASE was called for the
second time on the same file descriptor.

This bug is a regression of 2.6.37 and is described here:
https://bugzilla.kernel.org/show_bug.cgi?id=43336

This patch reverts a commit from Oct 2004 (with subject "nfs4 lease:
move the f_delown processing") which originally introduced the
lm_release_private callback.

Signed-off-by: Filipe Brandenburger <filbranden@gmail.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/locks.c

index 814c51d0de4739e4b89e9091e00c17f284c0e2ba..86668dd211ae07384d80235a111b832936e31a90 100644 (file)
@@ -427,18 +427,8 @@ static void lease_break_callback(struct file_lock *fl)
        kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG);
 }
 
-static void lease_release_private_callback(struct file_lock *fl)
-{
-       if (!fl->fl_file)
-               return;
-
-       f_delown(fl->fl_file);
-       fl->fl_file->f_owner.signum = 0;
-}
-
 static const struct lock_manager_operations lease_manager_ops = {
        .lm_break = lease_break_callback,
-       .lm_release_private = lease_release_private_callback,
        .lm_change = lease_modify,
 };
 
@@ -1155,8 +1145,13 @@ int lease_modify(struct file_lock **before, int arg)
                return error;
        lease_clear_pending(fl, arg);
        locks_wake_up_blocks(fl);
-       if (arg == F_UNLCK)
+       if (arg == F_UNLCK) {
+               struct file *filp = fl->fl_file;
+
+               f_delown(filp);
+               filp->f_owner.signum = 0;
                locks_delete_lock(before);
+       }
        return 0;
 }