Skip to content

Commit 5c1a712

Browse files
committed
Merge tag 'ceph-for-6.2-rc3' of https://github.com/ceph/ceph-client
Pull ceph fixes from Ilya Dryomov: "Two file locking fixes from Xiubo" * tag 'ceph-for-6.2-rc3' of https://github.com/ceph/ceph-client: ceph: avoid use-after-free in ceph_fl_release_lock() ceph: switch to vfs_inode_has_locks() to fix file lock bug
2 parents 7b8c854 + 8e18587 commit 5c1a712

File tree

4 files changed

+22
-8
lines changed

4 files changed

+22
-8
lines changed

fs/ceph/caps.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2913,7 +2913,7 @@ int ceph_get_caps(struct file *filp, int need, int want, loff_t endoff, int *got
29132913

29142914
while (true) {
29152915
flags &= CEPH_FILE_MODE_MASK;
2916-
if (atomic_read(&fi->num_locks))
2916+
if (vfs_inode_has_locks(inode))
29172917
flags |= CHECK_FILELOCK;
29182918
_got = 0;
29192919
ret = try_get_cap_refs(inode, need, want, endoff,

fs/ceph/locks.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,24 +32,36 @@ void __init ceph_flock_init(void)
3232

3333
static void ceph_fl_copy_lock(struct file_lock *dst, struct file_lock *src)
3434
{
35-
struct ceph_file_info *fi = dst->fl_file->private_data;
3635
struct inode *inode = file_inode(dst->fl_file);
3736
atomic_inc(&ceph_inode(inode)->i_filelock_ref);
38-
atomic_inc(&fi->num_locks);
37+
dst->fl_u.ceph.inode = igrab(inode);
3938
}
4039

40+
/*
41+
* Do not use the 'fl->fl_file' in release function, which
42+
* is possibly already released by another thread.
43+
*/
4144
static void ceph_fl_release_lock(struct file_lock *fl)
4245
{
43-
struct ceph_file_info *fi = fl->fl_file->private_data;
44-
struct inode *inode = file_inode(fl->fl_file);
45-
struct ceph_inode_info *ci = ceph_inode(inode);
46-
atomic_dec(&fi->num_locks);
46+
struct inode *inode = fl->fl_u.ceph.inode;
47+
struct ceph_inode_info *ci;
48+
49+
/*
50+
* If inode is NULL it should be a request file_lock,
51+
* nothing we can do.
52+
*/
53+
if (!inode)
54+
return;
55+
56+
ci = ceph_inode(inode);
4757
if (atomic_dec_and_test(&ci->i_filelock_ref)) {
4858
/* clear error when all locks are released */
4959
spin_lock(&ci->i_ceph_lock);
5060
ci->i_ceph_flags &= ~CEPH_I_ERROR_FILELOCK;
5161
spin_unlock(&ci->i_ceph_lock);
5262
}
63+
fl->fl_u.ceph.inode = NULL;
64+
iput(inode);
5365
}
5466

5567
static const struct file_lock_operations ceph_fl_lock_ops = {

fs/ceph/super.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,6 @@ struct ceph_file_info {
790790
struct list_head rw_contexts;
791791

792792
u32 filp_gen;
793-
atomic_t num_locks;
794793
};
795794

796795
struct ceph_dir_file_info {

include/linux/fs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,6 +1119,9 @@ struct file_lock {
11191119
int state; /* state of grant or error if -ve */
11201120
unsigned int debug_id;
11211121
} afs;
1122+
struct {
1123+
struct inode *inode;
1124+
} ceph;
11221125
} fl_u;
11231126
} __randomize_layout;
11241127

0 commit comments

Comments
 (0)