diff --git a/fs/locks.c b/fs/locks.c index da57c9b7e8445934b86f2ae760b2e25c5df37ff3..717fbc404e6b2ac1522175758cc365a847ca0c52 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -431,7 +431,7 @@ static int lease_init(struct file *filp, long type, struct file_lock *fl) if (assign_type(fl, type) != 0) return -EINVAL; - fl->fl_owner = (fl_owner_t)filp; + fl->fl_owner = (fl_owner_t)current->files; fl->fl_pid = current->tgid; fl->fl_file = filp; diff --git a/include/linux/fs.h b/include/linux/fs.h index 338e6f758c6d922be7d8163361da051efa0e3cbc..e11d60cc867bd9010edc8d2425cce03b228d968f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1921,6 +1921,12 @@ static inline int break_lease(struct inode *inode, unsigned int mode) static inline int break_deleg(struct inode *inode, unsigned int mode) { + /* + * Since this check is lockless, we must ensure that any refcounts + * taken are done before checking inode->i_flock. Otherwise, we could + * end up racing with tasks trying to set a new lease on this file. + */ + smp_mb(); if (inode->i_flock) return __break_lease(inode, mode, FL_DELEG); return 0;