Skip to content

Commit fb4d33a

Browse files
committed
Merge tag '6.16-rc2-ksmbd-server-fixes' of git://git.samba.org/ksmbd
Pull smb server fixes from Steve French: - Fix alternate data streams bug - Important fix for null pointer deref with Kerberos authentication - Fix oops in smbdirect (RDMA) in free_transport * tag '6.16-rc2-ksmbd-server-fixes' of git://git.samba.org/ksmbd: ksmbd: handle set/get info file for streamed file ksmbd: fix null pointer dereference in destroy_previous_session ksmbd: add free_transport ops in ksmbd connection
2 parents 229f135 + 4ea0bb8 commit fb4d33a

File tree

7 files changed

+72
-24
lines changed

7 files changed

+72
-24
lines changed

fs/smb/server/connection.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ void ksmbd_conn_free(struct ksmbd_conn *conn)
4040
kvfree(conn->request_buf);
4141
kfree(conn->preauth_info);
4242
if (atomic_dec_and_test(&conn->refcnt)) {
43-
ksmbd_free_transport(conn->transport);
43+
conn->transport->ops->free_transport(conn->transport);
4444
kfree(conn);
4545
}
4646
}

fs/smb/server/connection.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ struct ksmbd_transport_ops {
133133
void *buf, unsigned int len,
134134
struct smb2_buffer_desc_v1 *desc,
135135
unsigned int desc_len);
136+
void (*free_transport)(struct ksmbd_transport *kt);
136137
};
137138

138139
struct ksmbd_transport {

fs/smb/server/smb2pdu.c

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,17 +1607,18 @@ static int krb5_authenticate(struct ksmbd_work *work,
16071607
out_len = work->response_sz -
16081608
(le16_to_cpu(rsp->SecurityBufferOffset) + 4);
16091609

1610-
/* Check previous session */
1611-
prev_sess_id = le64_to_cpu(req->PreviousSessionId);
1612-
if (prev_sess_id && prev_sess_id != sess->id)
1613-
destroy_previous_session(conn, sess->user, prev_sess_id);
1614-
16151610
retval = ksmbd_krb5_authenticate(sess, in_blob, in_len,
16161611
out_blob, &out_len);
16171612
if (retval) {
16181613
ksmbd_debug(SMB, "krb5 authentication failed\n");
16191614
return -EINVAL;
16201615
}
1616+
1617+
/* Check previous session */
1618+
prev_sess_id = le64_to_cpu(req->PreviousSessionId);
1619+
if (prev_sess_id && prev_sess_id != sess->id)
1620+
destroy_previous_session(conn, sess->user, prev_sess_id);
1621+
16211622
rsp->SecurityBufferLength = cpu_to_le16(out_len);
16221623

16231624
if ((conn->sign || server_conf.enforced_signing) ||
@@ -4871,8 +4872,13 @@ static int get_file_standard_info(struct smb2_query_info_rsp *rsp,
48714872
sinfo = (struct smb2_file_standard_info *)rsp->Buffer;
48724873
delete_pending = ksmbd_inode_pending_delete(fp);
48734874

4874-
sinfo->AllocationSize = cpu_to_le64(stat.blocks << 9);
4875-
sinfo->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
4875+
if (ksmbd_stream_fd(fp) == false) {
4876+
sinfo->AllocationSize = cpu_to_le64(stat.blocks << 9);
4877+
sinfo->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
4878+
} else {
4879+
sinfo->AllocationSize = cpu_to_le64(fp->stream.size);
4880+
sinfo->EndOfFile = cpu_to_le64(fp->stream.size);
4881+
}
48764882
sinfo->NumberOfLinks = cpu_to_le32(get_nlink(&stat) - delete_pending);
48774883
sinfo->DeletePending = delete_pending;
48784884
sinfo->Directory = S_ISDIR(stat.mode) ? 1 : 0;
@@ -4935,9 +4941,14 @@ static int get_file_all_info(struct ksmbd_work *work,
49354941
file_info->ChangeTime = cpu_to_le64(time);
49364942
file_info->Attributes = fp->f_ci->m_fattr;
49374943
file_info->Pad1 = 0;
4938-
file_info->AllocationSize =
4939-
cpu_to_le64(stat.blocks << 9);
4940-
file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
4944+
if (ksmbd_stream_fd(fp) == false) {
4945+
file_info->AllocationSize =
4946+
cpu_to_le64(stat.blocks << 9);
4947+
file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
4948+
} else {
4949+
file_info->AllocationSize = cpu_to_le64(fp->stream.size);
4950+
file_info->EndOfFile = cpu_to_le64(fp->stream.size);
4951+
}
49414952
file_info->NumberOfLinks =
49424953
cpu_to_le32(get_nlink(&stat) - delete_pending);
49434954
file_info->DeletePending = delete_pending;
@@ -4946,7 +4957,10 @@ static int get_file_all_info(struct ksmbd_work *work,
49464957
file_info->IndexNumber = cpu_to_le64(stat.ino);
49474958
file_info->EASize = 0;
49484959
file_info->AccessFlags = fp->daccess;
4949-
file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos);
4960+
if (ksmbd_stream_fd(fp) == false)
4961+
file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos);
4962+
else
4963+
file_info->CurrentByteOffset = cpu_to_le64(fp->stream.pos);
49504964
file_info->Mode = fp->coption;
49514965
file_info->AlignmentRequirement = 0;
49524966
conv_len = smbConvertToUTF16((__le16 *)file_info->FileName, filename,
@@ -5134,8 +5148,13 @@ static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
51345148
time = ksmbd_UnixTimeToNT(stat.ctime);
51355149
file_info->ChangeTime = cpu_to_le64(time);
51365150
file_info->Attributes = fp->f_ci->m_fattr;
5137-
file_info->AllocationSize = cpu_to_le64(stat.blocks << 9);
5138-
file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
5151+
if (ksmbd_stream_fd(fp) == false) {
5152+
file_info->AllocationSize = cpu_to_le64(stat.blocks << 9);
5153+
file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
5154+
} else {
5155+
file_info->AllocationSize = cpu_to_le64(fp->stream.size);
5156+
file_info->EndOfFile = cpu_to_le64(fp->stream.size);
5157+
}
51395158
file_info->Reserved = cpu_to_le32(0);
51405159
rsp->OutputBufferLength =
51415160
cpu_to_le32(sizeof(struct smb2_file_ntwrk_info));
@@ -5158,7 +5177,11 @@ static void get_file_position_info(struct smb2_query_info_rsp *rsp,
51585177
struct smb2_file_pos_info *file_info;
51595178

51605179
file_info = (struct smb2_file_pos_info *)rsp->Buffer;
5161-
file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos);
5180+
if (ksmbd_stream_fd(fp) == false)
5181+
file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos);
5182+
else
5183+
file_info->CurrentByteOffset = cpu_to_le64(fp->stream.pos);
5184+
51625185
rsp->OutputBufferLength =
51635186
cpu_to_le32(sizeof(struct smb2_file_pos_info));
51645187
}
@@ -5247,8 +5270,13 @@ static int find_file_posix_info(struct smb2_query_info_rsp *rsp,
52475270
file_info->ChangeTime = cpu_to_le64(time);
52485271
file_info->DosAttributes = fp->f_ci->m_fattr;
52495272
file_info->Inode = cpu_to_le64(stat.ino);
5250-
file_info->EndOfFile = cpu_to_le64(stat.size);
5251-
file_info->AllocationSize = cpu_to_le64(stat.blocks << 9);
5273+
if (ksmbd_stream_fd(fp) == false) {
5274+
file_info->EndOfFile = cpu_to_le64(stat.size);
5275+
file_info->AllocationSize = cpu_to_le64(stat.blocks << 9);
5276+
} else {
5277+
file_info->EndOfFile = cpu_to_le64(fp->stream.size);
5278+
file_info->AllocationSize = cpu_to_le64(fp->stream.size);
5279+
}
52525280
file_info->HardLinks = cpu_to_le32(stat.nlink);
52535281
file_info->Mode = cpu_to_le32(stat.mode & 0777);
52545282
switch (stat.mode & S_IFMT) {
@@ -6190,6 +6218,9 @@ static int set_file_allocation_info(struct ksmbd_work *work,
61906218
if (!(fp->daccess & FILE_WRITE_DATA_LE))
61916219
return -EACCES;
61926220

6221+
if (ksmbd_stream_fd(fp) == true)
6222+
return 0;
6223+
61936224
rc = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
61946225
AT_STATX_SYNC_AS_STAT);
61956226
if (rc)
@@ -6248,7 +6279,8 @@ static int set_end_of_file_info(struct ksmbd_work *work, struct ksmbd_file *fp,
62486279
* truncate of some filesystem like FAT32 fill zero data in
62496280
* truncated range.
62506281
*/
6251-
if (inode->i_sb->s_magic != MSDOS_SUPER_MAGIC) {
6282+
if (inode->i_sb->s_magic != MSDOS_SUPER_MAGIC &&
6283+
ksmbd_stream_fd(fp) == false) {
62526284
ksmbd_debug(SMB, "truncated to newsize %lld\n", newsize);
62536285
rc = ksmbd_vfs_truncate(work, fp, newsize);
62546286
if (rc) {
@@ -6321,7 +6353,13 @@ static int set_file_position_info(struct ksmbd_file *fp,
63216353
return -EINVAL;
63226354
}
63236355

6324-
fp->filp->f_pos = current_byte_offset;
6356+
if (ksmbd_stream_fd(fp) == false)
6357+
fp->filp->f_pos = current_byte_offset;
6358+
else {
6359+
if (current_byte_offset > XATTR_SIZE_MAX)
6360+
current_byte_offset = XATTR_SIZE_MAX;
6361+
fp->stream.pos = current_byte_offset;
6362+
}
63256363
return 0;
63266364
}
63276365

fs/smb/server/transport_rdma.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,8 @@ struct smb_direct_transport {
159159
};
160160

161161
#define KSMBD_TRANS(t) ((struct ksmbd_transport *)&((t)->transport))
162-
162+
#define SMBD_TRANS(t) ((struct smb_direct_transport *)container_of(t, \
163+
struct smb_direct_transport, transport))
163164
enum {
164165
SMB_DIRECT_MSG_NEGOTIATE_REQ = 0,
165166
SMB_DIRECT_MSG_DATA_TRANSFER
@@ -410,6 +411,11 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
410411
return NULL;
411412
}
412413

414+
static void smb_direct_free_transport(struct ksmbd_transport *kt)
415+
{
416+
kfree(SMBD_TRANS(kt));
417+
}
418+
413419
static void free_transport(struct smb_direct_transport *t)
414420
{
415421
struct smb_direct_recvmsg *recvmsg;
@@ -455,7 +461,6 @@ static void free_transport(struct smb_direct_transport *t)
455461

456462
smb_direct_destroy_pools(t);
457463
ksmbd_conn_free(KSMBD_TRANS(t)->conn);
458-
kfree(t);
459464
}
460465

461466
static struct smb_direct_sendmsg
@@ -2281,4 +2286,5 @@ static const struct ksmbd_transport_ops ksmbd_smb_direct_transport_ops = {
22812286
.read = smb_direct_read,
22822287
.rdma_read = smb_direct_rdma_read,
22832288
.rdma_write = smb_direct_rdma_write,
2289+
.free_transport = smb_direct_free_transport,
22842290
};

fs/smb/server/transport_tcp.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ static struct tcp_transport *alloc_transport(struct socket *client_sk)
9393
return t;
9494
}
9595

96-
void ksmbd_free_transport(struct ksmbd_transport *kt)
96+
static void ksmbd_tcp_free_transport(struct ksmbd_transport *kt)
9797
{
9898
struct tcp_transport *t = TCP_TRANS(kt);
9999

@@ -656,4 +656,5 @@ static const struct ksmbd_transport_ops ksmbd_tcp_transport_ops = {
656656
.read = ksmbd_tcp_read,
657657
.writev = ksmbd_tcp_writev,
658658
.disconnect = ksmbd_tcp_disconnect,
659+
.free_transport = ksmbd_tcp_free_transport,
659660
};

fs/smb/server/vfs.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ static int ksmbd_vfs_stream_read(struct ksmbd_file *fp, char *buf, loff_t *pos,
293293

294294
if (v_len - *pos < count)
295295
count = v_len - *pos;
296+
fp->stream.pos = v_len;
296297

297298
memcpy(buf, &stream_buf[*pos], count);
298299

@@ -456,8 +457,8 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
456457
true);
457458
if (err < 0)
458459
goto out;
459-
460-
fp->filp->f_pos = *pos;
460+
else
461+
fp->stream.pos = size;
461462
err = 0;
462463
out:
463464
kvfree(stream_buf);

fs/smb/server/vfs_cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ struct ksmbd_lock {
4444
struct stream {
4545
char *name;
4646
ssize_t size;
47+
loff_t pos;
4748
};
4849

4950
struct ksmbd_inode {

0 commit comments

Comments
 (0)