Commit fb4d33ab authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents 229f135e 4ea0bb8a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ void ksmbd_conn_free(struct ksmbd_conn *conn)
	kvfree(conn->request_buf);
	kfree(conn->preauth_info);
	if (atomic_dec_and_test(&conn->refcnt)) {
		ksmbd_free_transport(conn->transport);
		conn->transport->ops->free_transport(conn->transport);
		kfree(conn);
	}
}
+1 −0
Original line number Diff line number Diff line
@@ -133,6 +133,7 @@ struct ksmbd_transport_ops {
			  void *buf, unsigned int len,
			  struct smb2_buffer_desc_v1 *desc,
			  unsigned int desc_len);
	void (*free_transport)(struct ksmbd_transport *kt);
};

struct ksmbd_transport {
+56 −18
Original line number Diff line number Diff line
@@ -1607,17 +1607,18 @@ static int krb5_authenticate(struct ksmbd_work *work,
	out_len = work->response_sz -
		(le16_to_cpu(rsp->SecurityBufferOffset) + 4);

	/* Check previous session */
	prev_sess_id = le64_to_cpu(req->PreviousSessionId);
	if (prev_sess_id && prev_sess_id != sess->id)
		destroy_previous_session(conn, sess->user, prev_sess_id);

	retval = ksmbd_krb5_authenticate(sess, in_blob, in_len,
					 out_blob, &out_len);
	if (retval) {
		ksmbd_debug(SMB, "krb5 authentication failed\n");
		return -EINVAL;
	}

	/* Check previous session */
	prev_sess_id = le64_to_cpu(req->PreviousSessionId);
	if (prev_sess_id && prev_sess_id != sess->id)
		destroy_previous_session(conn, sess->user, prev_sess_id);

	rsp->SecurityBufferLength = cpu_to_le16(out_len);

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

	if (ksmbd_stream_fd(fp) == false) {
		sinfo->AllocationSize = cpu_to_le64(stat.blocks << 9);
		sinfo->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
	} else {
		sinfo->AllocationSize = cpu_to_le64(fp->stream.size);
		sinfo->EndOfFile = cpu_to_le64(fp->stream.size);
	}
	sinfo->NumberOfLinks = cpu_to_le32(get_nlink(&stat) - delete_pending);
	sinfo->DeletePending = delete_pending;
	sinfo->Directory = S_ISDIR(stat.mode) ? 1 : 0;
@@ -4935,9 +4941,14 @@ static int get_file_all_info(struct ksmbd_work *work,
	file_info->ChangeTime = cpu_to_le64(time);
	file_info->Attributes = fp->f_ci->m_fattr;
	file_info->Pad1 = 0;
	if (ksmbd_stream_fd(fp) == false) {
		file_info->AllocationSize =
			cpu_to_le64(stat.blocks << 9);
		file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
	} else {
		file_info->AllocationSize = cpu_to_le64(fp->stream.size);
		file_info->EndOfFile = cpu_to_le64(fp->stream.size);
	}
	file_info->NumberOfLinks =
			cpu_to_le32(get_nlink(&stat) - delete_pending);
	file_info->DeletePending = delete_pending;
@@ -4946,7 +4957,10 @@ static int get_file_all_info(struct ksmbd_work *work,
	file_info->IndexNumber = cpu_to_le64(stat.ino);
	file_info->EASize = 0;
	file_info->AccessFlags = fp->daccess;
	if (ksmbd_stream_fd(fp) == false)
		file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos);
	else
		file_info->CurrentByteOffset = cpu_to_le64(fp->stream.pos);
	file_info->Mode = fp->coption;
	file_info->AlignmentRequirement = 0;
	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,
	time = ksmbd_UnixTimeToNT(stat.ctime);
	file_info->ChangeTime = cpu_to_le64(time);
	file_info->Attributes = fp->f_ci->m_fattr;
	if (ksmbd_stream_fd(fp) == false) {
		file_info->AllocationSize = cpu_to_le64(stat.blocks << 9);
		file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
	} else {
		file_info->AllocationSize = cpu_to_le64(fp->stream.size);
		file_info->EndOfFile = cpu_to_le64(fp->stream.size);
	}
	file_info->Reserved = cpu_to_le32(0);
	rsp->OutputBufferLength =
		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,
	struct smb2_file_pos_info *file_info;

	file_info = (struct smb2_file_pos_info *)rsp->Buffer;
	if (ksmbd_stream_fd(fp) == false)
		file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos);
	else
		file_info->CurrentByteOffset = cpu_to_le64(fp->stream.pos);

	rsp->OutputBufferLength =
		cpu_to_le32(sizeof(struct smb2_file_pos_info));
}
@@ -5247,8 +5270,13 @@ static int find_file_posix_info(struct smb2_query_info_rsp *rsp,
	file_info->ChangeTime = cpu_to_le64(time);
	file_info->DosAttributes = fp->f_ci->m_fattr;
	file_info->Inode = cpu_to_le64(stat.ino);
	if (ksmbd_stream_fd(fp) == false) {
		file_info->EndOfFile = cpu_to_le64(stat.size);
		file_info->AllocationSize = cpu_to_le64(stat.blocks << 9);
	} else {
		file_info->EndOfFile = cpu_to_le64(fp->stream.size);
		file_info->AllocationSize = cpu_to_le64(fp->stream.size);
	}
	file_info->HardLinks = cpu_to_le32(stat.nlink);
	file_info->Mode = cpu_to_le32(stat.mode & 0777);
	switch (stat.mode & S_IFMT) {
@@ -6190,6 +6218,9 @@ static int set_file_allocation_info(struct ksmbd_work *work,
	if (!(fp->daccess & FILE_WRITE_DATA_LE))
		return -EACCES;

	if (ksmbd_stream_fd(fp) == true)
		return 0;

	rc = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
			 AT_STATX_SYNC_AS_STAT);
	if (rc)
@@ -6248,7 +6279,8 @@ static int set_end_of_file_info(struct ksmbd_work *work, struct ksmbd_file *fp,
	 * truncate of some filesystem like FAT32 fill zero data in
	 * truncated range.
	 */
	if (inode->i_sb->s_magic != MSDOS_SUPER_MAGIC) {
	if (inode->i_sb->s_magic != MSDOS_SUPER_MAGIC &&
	    ksmbd_stream_fd(fp) == false) {
		ksmbd_debug(SMB, "truncated to newsize %lld\n", newsize);
		rc = ksmbd_vfs_truncate(work, fp, newsize);
		if (rc) {
@@ -6321,7 +6353,13 @@ static int set_file_position_info(struct ksmbd_file *fp,
		return -EINVAL;
	}

	if (ksmbd_stream_fd(fp) == false)
		fp->filp->f_pos = current_byte_offset;
	else {
		if (current_byte_offset > XATTR_SIZE_MAX)
			current_byte_offset = XATTR_SIZE_MAX;
		fp->stream.pos = current_byte_offset;
	}
	return 0;
}

+8 −2
Original line number Diff line number Diff line
@@ -159,7 +159,8 @@ struct smb_direct_transport {
};

#define KSMBD_TRANS(t) ((struct ksmbd_transport *)&((t)->transport))

#define SMBD_TRANS(t)	((struct smb_direct_transport *)container_of(t, \
				struct smb_direct_transport, transport))
enum {
	SMB_DIRECT_MSG_NEGOTIATE_REQ = 0,
	SMB_DIRECT_MSG_DATA_TRANSFER
@@ -410,6 +411,11 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
	return NULL;
}

static void smb_direct_free_transport(struct ksmbd_transport *kt)
{
	kfree(SMBD_TRANS(kt));
}

static void free_transport(struct smb_direct_transport *t)
{
	struct smb_direct_recvmsg *recvmsg;
@@ -455,7 +461,6 @@ static void free_transport(struct smb_direct_transport *t)

	smb_direct_destroy_pools(t);
	ksmbd_conn_free(KSMBD_TRANS(t)->conn);
	kfree(t);
}

static struct smb_direct_sendmsg
@@ -2281,4 +2286,5 @@ static const struct ksmbd_transport_ops ksmbd_smb_direct_transport_ops = {
	.read		= smb_direct_read,
	.rdma_read	= smb_direct_rdma_read,
	.rdma_write	= smb_direct_rdma_write,
	.free_transport = smb_direct_free_transport,
};
+2 −1
Original line number Diff line number Diff line
@@ -93,7 +93,7 @@ static struct tcp_transport *alloc_transport(struct socket *client_sk)
	return t;
}

void ksmbd_free_transport(struct ksmbd_transport *kt)
static void ksmbd_tcp_free_transport(struct ksmbd_transport *kt)
{
	struct tcp_transport *t = TCP_TRANS(kt);

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