Skip to content

Commit b29fb88

Browse files
committed
Merge tag 'v7.0-rc3-ksmbd-server-fixes' of git://git.samba.org/ksmbd
Pull smb server fixes from Steve French: - Fix potential use after free errors - Fix refcount leak in smb2 open error path - Prevent allowing logging signing or encryption keys * tag 'v7.0-rc3-ksmbd-server-fixes' of git://git.samba.org/ksmbd: ksmbd: Don't log keys in SMB3 signing and encryption key generation smb: server: fix use-after-free in smb2_open() ksmbd: fix use-after-free in smb_lazy_parent_lease_break_close() ksmbd: fix use-after-free by using call_rcu() for oplock_info ksmbd: fix use-after-free in proc_show_files due to early rcu_read_unlock smb/server: Fix another refcount leak in smb2_open()
2 parents b4f0dd3 + 4413361 commit b29fb88

5 files changed

Lines changed: 39 additions & 41 deletions

File tree

fs/smb/server/auth.c

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -589,12 +589,8 @@ static int generate_smb3signingkey(struct ksmbd_session *sess,
589589
if (!(conn->dialect >= SMB30_PROT_ID && signing->binding))
590590
memcpy(chann->smb3signingkey, key, SMB3_SIGN_KEY_SIZE);
591591

592-
ksmbd_debug(AUTH, "dumping generated AES signing keys\n");
592+
ksmbd_debug(AUTH, "generated SMB3 signing key\n");
593593
ksmbd_debug(AUTH, "Session Id %llu\n", sess->id);
594-
ksmbd_debug(AUTH, "Session Key %*ph\n",
595-
SMB2_NTLMV2_SESSKEY_SIZE, sess->sess_key);
596-
ksmbd_debug(AUTH, "Signing Key %*ph\n",
597-
SMB3_SIGN_KEY_SIZE, key);
598594
return 0;
599595
}
600596

@@ -652,23 +648,9 @@ static void generate_smb3encryptionkey(struct ksmbd_conn *conn,
652648
ptwin->decryption.context,
653649
sess->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE);
654650

655-
ksmbd_debug(AUTH, "dumping generated AES encryption keys\n");
651+
ksmbd_debug(AUTH, "generated SMB3 encryption/decryption keys\n");
656652
ksmbd_debug(AUTH, "Cipher type %d\n", conn->cipher_type);
657653
ksmbd_debug(AUTH, "Session Id %llu\n", sess->id);
658-
ksmbd_debug(AUTH, "Session Key %*ph\n",
659-
SMB2_NTLMV2_SESSKEY_SIZE, sess->sess_key);
660-
if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
661-
conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) {
662-
ksmbd_debug(AUTH, "ServerIn Key %*ph\n",
663-
SMB3_GCM256_CRYPTKEY_SIZE, sess->smb3encryptionkey);
664-
ksmbd_debug(AUTH, "ServerOut Key %*ph\n",
665-
SMB3_GCM256_CRYPTKEY_SIZE, sess->smb3decryptionkey);
666-
} else {
667-
ksmbd_debug(AUTH, "ServerIn Key %*ph\n",
668-
SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3encryptionkey);
669-
ksmbd_debug(AUTH, "ServerOut Key %*ph\n",
670-
SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3decryptionkey);
671-
}
672654
}
673655

674656
void ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,

fs/smb/server/oplock.c

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ static void free_lease(struct oplock_info *opinfo)
120120
kfree(lease);
121121
}
122122

123-
static void free_opinfo(struct oplock_info *opinfo)
123+
static void __free_opinfo(struct oplock_info *opinfo)
124124
{
125125
if (opinfo->is_lease)
126126
free_lease(opinfo);
@@ -129,6 +129,18 @@ static void free_opinfo(struct oplock_info *opinfo)
129129
kfree(opinfo);
130130
}
131131

132+
static void free_opinfo_rcu(struct rcu_head *rcu)
133+
{
134+
struct oplock_info *opinfo = container_of(rcu, struct oplock_info, rcu);
135+
136+
__free_opinfo(opinfo);
137+
}
138+
139+
static void free_opinfo(struct oplock_info *opinfo)
140+
{
141+
call_rcu(&opinfo->rcu, free_opinfo_rcu);
142+
}
143+
132144
struct oplock_info *opinfo_get(struct ksmbd_file *fp)
133145
{
134146
struct oplock_info *opinfo;
@@ -176,9 +188,9 @@ void opinfo_put(struct oplock_info *opinfo)
176188
free_opinfo(opinfo);
177189
}
178190

179-
static void opinfo_add(struct oplock_info *opinfo)
191+
static void opinfo_add(struct oplock_info *opinfo, struct ksmbd_file *fp)
180192
{
181-
struct ksmbd_inode *ci = opinfo->o_fp->f_ci;
193+
struct ksmbd_inode *ci = fp->f_ci;
182194

183195
down_write(&ci->m_lock);
184196
list_add(&opinfo->op_entry, &ci->m_op_list);
@@ -1123,10 +1135,12 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)
11231135

11241136
rcu_read_lock();
11251137
opinfo = rcu_dereference(fp->f_opinfo);
1126-
rcu_read_unlock();
11271138

1128-
if (!opinfo || !opinfo->is_lease || opinfo->o_lease->version != 2)
1139+
if (!opinfo || !opinfo->is_lease || opinfo->o_lease->version != 2) {
1140+
rcu_read_unlock();
11291141
return;
1142+
}
1143+
rcu_read_unlock();
11301144

11311145
p_ci = ksmbd_inode_lookup_lock(fp->filp->f_path.dentry->d_parent);
11321146
if (!p_ci)
@@ -1277,20 +1291,21 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
12771291
set_oplock_level(opinfo, req_op_level, lctx);
12781292

12791293
out:
1280-
rcu_assign_pointer(fp->f_opinfo, opinfo);
1281-
opinfo->o_fp = fp;
1282-
12831294
opinfo_count_inc(fp);
1284-
opinfo_add(opinfo);
1295+
opinfo_add(opinfo, fp);
1296+
12851297
if (opinfo->is_lease) {
12861298
err = add_lease_global_list(opinfo);
12871299
if (err)
12881300
goto err_out;
12891301
}
12901302

1303+
rcu_assign_pointer(fp->f_opinfo, opinfo);
1304+
opinfo->o_fp = fp;
1305+
12911306
return 0;
12921307
err_out:
1293-
free_opinfo(opinfo);
1308+
__free_opinfo(opinfo);
12941309
return err;
12951310
}
12961311

fs/smb/server/oplock.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,9 @@ struct oplock_info {
6969
struct lease *o_lease;
7070
struct list_head op_entry;
7171
struct list_head lease_entry;
72-
wait_queue_head_t oplock_q; /* Other server threads */
73-
wait_queue_head_t oplock_brk; /* oplock breaking wait */
72+
wait_queue_head_t oplock_q; /* Other server threads */
73+
wait_queue_head_t oplock_brk; /* oplock breaking wait */
74+
struct rcu_head rcu;
7475
};
7576

7677
struct lease_break_info {

fs/smb/server/smb2pdu.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3012,13 +3012,14 @@ int smb2_open(struct ksmbd_work *work)
30123012
goto err_out2;
30133013
}
30143014

3015+
fp = dh_info.fp;
3016+
30153017
if (ksmbd_override_fsids(work)) {
30163018
rc = -ENOMEM;
30173019
ksmbd_put_durable_fd(dh_info.fp);
30183020
goto err_out2;
30193021
}
30203022

3021-
fp = dh_info.fp;
30223023
file_info = FILE_OPENED;
30233024

30243025
rc = ksmbd_vfs_getattr(&fp->filp->f_path, &stat);
@@ -3616,10 +3617,8 @@ int smb2_open(struct ksmbd_work *work)
36163617

36173618
reconnected_fp:
36183619
rsp->StructureSize = cpu_to_le16(89);
3619-
rcu_read_lock();
3620-
opinfo = rcu_dereference(fp->f_opinfo);
3620+
opinfo = opinfo_get(fp);
36213621
rsp->OplockLevel = opinfo != NULL ? opinfo->level : 0;
3622-
rcu_read_unlock();
36233622
rsp->Flags = 0;
36243623
rsp->CreateAction = cpu_to_le32(file_info);
36253624
rsp->CreationTime = cpu_to_le64(fp->create_time);
@@ -3660,6 +3659,7 @@ int smb2_open(struct ksmbd_work *work)
36603659
next_ptr = &lease_ccontext->Next;
36613660
next_off = conn->vals->create_lease_size;
36623661
}
3662+
opinfo_put(opinfo);
36633663

36643664
if (maximal_access_ctxt) {
36653665
struct create_context *mxac_ccontext;

fs/smb/server/vfs_cache.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,7 @@ static int proc_show_files(struct seq_file *m, void *v)
8787

8888
rcu_read_lock();
8989
opinfo = rcu_dereference(fp->f_opinfo);
90-
rcu_read_unlock();
91-
92-
if (!opinfo) {
93-
seq_printf(m, " %-15s", " ");
94-
} else {
90+
if (opinfo) {
9591
const struct ksmbd_const_name *const_names;
9692
int count;
9793
unsigned int level;
@@ -105,8 +101,12 @@ static int proc_show_files(struct seq_file *m, void *v)
105101
count = ARRAY_SIZE(ksmbd_oplock_const_names);
106102
level = opinfo->level;
107103
}
104+
rcu_read_unlock();
108105
ksmbd_proc_show_const_name(m, " %-15s",
109106
const_names, count, level);
107+
} else {
108+
rcu_read_unlock();
109+
seq_printf(m, " %-15s", " ");
110110
}
111111

112112
seq_printf(m, " %#010x %#010x %s\n",

0 commit comments

Comments
 (0)