* [PATCH 6.12.y 1/6] cifs: Remove the server pointer from smb_message
[not found] <2026090303-ashamed-silver-ed5c@gregkh>
@ 2026-09-07 15:00 ` Sasha Levin
2026-09-07 15:00 ` [PATCH 6.12.y 2/6] cifs: Do some preparation prior to organising the function declarations Sasha Levin
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Sasha Levin @ 2026-09-07 15:00 UTC (permalink / raw)
To: stable
Cc: David Howells, Paulo Alcantara (Red Hat), Shyam Prasad N,
Tom Talpey, linux-cifs, netfs, linux-fsdevel, Steve French,
Sasha Levin
From: David Howells <dhowells@redhat.com>
[ Upstream commit 87fba18abbb8433a47045c785f2edc027e4d2bc5 ]
Remove the server pointer from smb_message and instead pass it down to all
the things that access it.
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Paulo Alcantara (Red Hat) <pc@manguebit.org>
cc: Shyam Prasad N <sprasad@microsoft.com>
cc: Tom Talpey <tom@talpey.com> (RDMA, smbdirect)
cc: linux-cifs@vger.kernel.org
cc: netfs@lists.linux.dev
cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Steve French <stfrench@microsoft.com>
[ sashal: Reduced backport -- upstream 87fba18abbb84 touches 12 file(s), this
backport carries 10. Not backported here:
fs/smb/client/cifsfs.c
fs/smb/client/cifstransport.c
This note is generated from the file lists only; see the resolution record
for the reasoning. ]
Stable-dep-of: 730d0bb19507 ("smb: client: fix UAF and buffer leak in cifs_check_trans2() for malformed secondary T2")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/smb/client/cifsglob.h | 6 +--
fs/smb/client/cifsproto.h | 19 +++++----
fs/smb/client/cifssmb.c | 20 ++++------
fs/smb/client/connect.c | 29 +++++++-------
fs/smb/client/netmisc.c | 5 ++-
fs/smb/client/smb1ops.c | 4 +-
fs/smb/client/smb2ops.c | 22 +++++------
fs/smb/client/smb2pdu.c | 23 +++++------
fs/smb/client/smb2transport.c | 8 ++--
fs/smb/client/transport.c | 74 +++++++++++++++++------------------
10 files changed, 102 insertions(+), 108 deletions(-)
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index 3f9c03828cd4f..d61a6424f20ca 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -1630,7 +1630,8 @@ typedef int (mid_receive_t)(struct TCP_Server_Info *server,
* - it will be called by cifsd, with no locks held
* - the mid will be removed from any lists
*/
-typedef void (mid_callback_t)(struct mid_q_entry *mid);
+typedef void (mid_callback_t)(struct TCP_Server_Info *server,
+ struct mid_q_entry *mid);
/*
* This is the protopyte for mid handle function. This is called once the mid
@@ -1642,8 +1643,7 @@ typedef int (mid_handle_t)(struct TCP_Server_Info *server,
/* one of these for every pending CIFS request to the server */
struct mid_q_entry {
struct list_head qhead; /* mids waiting on reply from this server */
- struct kref refcount;
- struct TCP_Server_Info *server; /* server corresponding to this mid */
+ refcount_t refcount;
__u64 mid; /* multiplex id */
__u16 credits; /* number of credits consumed by this mid */
__u16 credits_received; /* number of credits from the response */
diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
index d2d004764a708..5f28eee91eb9d 100644
--- a/fs/smb/client/cifsproto.h
+++ b/fs/smb/client/cifsproto.h
@@ -83,9 +83,10 @@ extern char *cifs_build_path_to_root(struct smb3_fs_context *ctx,
int add_treename);
extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
char *cifs_build_devname(char *nodename, const char *prepath);
-extern void delete_mid(struct mid_q_entry *mid);
-void __release_mid(struct kref *refcount);
-extern void cifs_wake_up_task(struct mid_q_entry *mid);
+extern void delete_mid(struct TCP_Server_Info *server, struct mid_q_entry *mid);
+void __release_mid(struct TCP_Server_Info *server, struct mid_q_entry *mid);
+extern void cifs_wake_up_task(struct TCP_Server_Info *server,
+ struct mid_q_entry *mid);
extern int cifs_handle_standard(struct TCP_Server_Info *server,
struct mid_q_entry *mid);
extern char *smb3_fs_context_fullpath(const struct smb3_fs_context *ctx,
@@ -172,7 +173,8 @@ extern int decode_negTokenInit(unsigned char *security_blob, int length,
extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len);
extern void cifs_set_port(struct sockaddr *addr, const unsigned short int port);
extern int map_smb_to_linux_error(char *buf, bool logErr);
-extern int map_and_check_smb_error(struct mid_q_entry *mid, bool logErr);
+extern int map_and_check_smb_error(struct TCP_Server_Info *server,
+ struct mid_q_entry *mid, bool logErr);
extern void header_assemble(struct smb_hdr *, char /* command */ ,
const struct cifs_tcon *, int /* length of
fixed section (word count) in two byte units */);
@@ -255,7 +257,8 @@ extern unsigned int setup_special_mode_ACE(struct smb_ace *pace,
__u64 nmode);
extern unsigned int setup_special_user_owner_ACE(struct smb_ace *pace);
-extern void dequeue_mid(struct mid_q_entry *mid, bool malformed);
+extern void dequeue_mid(struct TCP_Server_Info *server,
+ struct mid_q_entry *mid, bool malformed);
extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
unsigned int to_read);
extern ssize_t cifs_discard_from_socket(struct TCP_Server_Info *server,
@@ -763,9 +766,11 @@ static inline bool dfs_src_pathname_equal(const char *s1, const char *s2)
return true;
}
-static inline void release_mid(struct mid_q_entry *mid)
+static inline void release_mid(struct TCP_Server_Info *server,
+ struct mid_q_entry *mid)
{
- kref_put(&mid->refcount, __release_mid);
+ if (refcount_dec_and_test(&mid->refcount))
+ __release_mid(server, mid);
}
static inline void cifs_free_open_info(struct cifs_open_info_data *data)
diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c
index 01c78d9e7ec0e..89f9c8d70109e 100644
--- a/fs/smb/client/cifssmb.c
+++ b/fs/smb/client/cifssmb.c
@@ -560,12 +560,11 @@ CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
* FIXME: maybe we should consider checking that the reply matches request?
*/
static void
-cifs_echo_callback(struct mid_q_entry *mid)
+cifs_echo_callback(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{
- struct TCP_Server_Info *server = mid->callback_data;
struct cifs_credits credits = { .value = 1, .instance = 0 };
- release_mid(mid);
+ release_mid(server, mid);
add_credits(server, &credits, CIFS_ECHO_OP);
}
@@ -1263,12 +1262,11 @@ CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
}
static void
-cifs_readv_callback(struct mid_q_entry *mid)
+cifs_readv_callback(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{
struct cifs_io_subrequest *rdata = mid->callback_data;
struct netfs_inode *ictx = netfs_inode(rdata->rreq->inode);
struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);
- struct TCP_Server_Info *server = tcon->ses->server;
struct smb_rqst rqst = { .rq_iov = rdata->iov,
.rq_nvec = 2,
.rq_iter = rdata->subreq.io_iter };
@@ -1331,7 +1329,7 @@ cifs_readv_callback(struct mid_q_entry *mid)
rdata->subreq.error = rdata->result;
rdata->subreq.transferred += rdata->got_bytes;
queue_work(cifsiod_wq, &rdata->subreq.work);
- release_mid(mid);
+ release_mid(server, mid);
add_credits(server, &credits, 0);
}
@@ -1638,11 +1636,9 @@ CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
* workqueue completion task.
*/
static void
-cifs_writev_callback(struct mid_q_entry *mid)
+cifs_writev_callback(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{
struct cifs_io_subrequest *wdata = mid->callback_data;
- struct TCP_Server_Info *server = wdata->server;
- struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);
WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
struct cifs_credits credits = {
.value = 1,
@@ -1655,7 +1651,7 @@ cifs_writev_callback(struct mid_q_entry *mid)
switch (mid->mid_state) {
case MID_RESPONSE_RECEIVED:
- result = cifs_check_receive(mid, tcon->ses->server, 0);
+ result = cifs_check_receive(mid, server, 0);
if (result != 0)
break;
@@ -1692,11 +1688,11 @@ cifs_writev_callback(struct mid_q_entry *mid)
0, cifs_trace_rw_credits_write_response_clear);
wdata->credits.value = 0;
cifs_write_subrequest_terminated(wdata, result, true);
- release_mid(mid);
+ release_mid(server, mid);
trace_smb3_rw_credits(credits.rreq_debug_id, credits.rreq_debug_index, 0,
server->credits, server->in_flight,
credits.value, cifs_trace_rw_credits_write_response_add);
- add_credits(tcon->ses->server, &credits, 0);
+ add_credits(server, &credits, 0);
}
/* cifs_async_writev - send an async write, and set up mid to handle result */
diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
index 52ac9b096a402..a550e51472c2f 100644
--- a/fs/smb/client/connect.c
+++ b/fs/smb/client/connect.c
@@ -339,7 +339,7 @@ cifs_abort_connection(struct TCP_Server_Info *server)
cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
spin_lock(&server->mid_lock);
list_for_each_entry_safe(mid, nmid, &server->pending_mid_q, qhead) {
- kref_get(&mid->refcount);
+ refcount_inc(&mid->refcount);
if (mid->mid_state == MID_REQUEST_SUBMITTED)
mid->mid_state = MID_RETRY_NEEDED;
list_move(&mid->qhead, &retry_list);
@@ -351,8 +351,8 @@ cifs_abort_connection(struct TCP_Server_Info *server)
cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
list_for_each_entry_safe(mid, nmid, &retry_list, qhead) {
list_del_init(&mid->qhead);
- mid->callback(mid);
- release_mid(mid);
+ mid->callback(server, mid);
+ release_mid(server, mid);
}
if (cifs_rdma_enabled(server)) {
@@ -866,12 +866,13 @@ is_smb_response(struct TCP_Server_Info *server, unsigned char type)
}
void
-dequeue_mid(struct mid_q_entry *mid, bool malformed)
+dequeue_mid(struct TCP_Server_Info *server, struct mid_q_entry *mid,
+ bool malformed)
{
#ifdef CONFIG_CIFS_STATS2
mid->when_received = jiffies;
#endif
- spin_lock(&mid->server->mid_lock);
+ spin_lock(&server->mid_lock);
if (!malformed)
mid->mid_state = MID_RESPONSE_RECEIVED;
else
@@ -881,12 +882,12 @@ dequeue_mid(struct mid_q_entry *mid, bool malformed)
* function has finished processing it is a bug.
*/
if (mid->mid_flags & MID_DELETED) {
- spin_unlock(&mid->server->mid_lock);
+ spin_unlock(&server->mid_lock);
pr_warn_once("trying to dequeue a deleted mid\n");
} else {
list_del_init(&mid->qhead);
mid->mid_flags |= MID_DELETED;
- spin_unlock(&mid->server->mid_lock);
+ spin_unlock(&server->mid_lock);
}
}
@@ -922,7 +923,7 @@ handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
else
server->smallbuf = NULL;
}
- dequeue_mid(mid, malformed);
+ dequeue_mid(server, mid, malformed);
}
int
@@ -1019,7 +1020,7 @@ clean_demultiplex_info(struct TCP_Server_Info *server)
list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
cifs_dbg(FYI, "Clearing mid %llu\n", mid_entry->mid);
- kref_get(&mid_entry->refcount);
+ refcount_inc(&mid_entry->refcount);
mid_entry->mid_state = MID_SHUTDOWN;
list_move(&mid_entry->qhead, &dispose_list);
mid_entry->mid_flags |= MID_DELETED;
@@ -1031,8 +1032,8 @@ clean_demultiplex_info(struct TCP_Server_Info *server)
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
cifs_dbg(FYI, "Callback mid %llu\n", mid_entry->mid);
list_del_init(&mid_entry->qhead);
- mid_entry->callback(mid_entry);
- release_mid(mid_entry);
+ mid_entry->callback(server, mid_entry);
+ release_mid(server, mid_entry);
}
/* 1/8th of sec is more than enough time for them to exit */
msleep(125);
@@ -1275,7 +1276,7 @@ cifs_demultiplex_thread(void *p)
if (length < 0) {
for (i = 0; i < num_mids; i++)
if (mids[i])
- release_mid(mids[i]);
+ release_mid(server, mids[i]);
continue;
}
@@ -1308,9 +1309,9 @@ cifs_demultiplex_thread(void *p)
}
if (!mids[i]->multiRsp || mids[i]->multiEnd)
- mids[i]->callback(mids[i]);
+ mids[i]->callback(server, mids[i]);
- release_mid(mids[i]);
+ release_mid(server, mids[i]);
} else if (server->ops->is_oplock_break &&
server->ops->is_oplock_break(bufs[i],
server)) {
diff --git a/fs/smb/client/netmisc.c b/fs/smb/client/netmisc.c
index 2a8d71221e5e7..8db57bd1a39de 100644
--- a/fs/smb/client/netmisc.c
+++ b/fs/smb/client/netmisc.c
@@ -881,7 +881,8 @@ map_smb_to_linux_error(char *buf, bool logErr)
}
int
-map_and_check_smb_error(struct mid_q_entry *mid, bool logErr)
+map_and_check_smb_error(struct TCP_Server_Info *server,
+ struct mid_q_entry *mid, bool logErr)
{
int rc;
struct smb_hdr *smb = (struct smb_hdr *)mid->resp_buf;
@@ -896,7 +897,7 @@ map_and_check_smb_error(struct mid_q_entry *mid, bool logErr)
if (class == ERRSRV && code == ERRbaduid) {
cifs_dbg(FYI, "Server returned 0x%x, reconnecting session...\n",
code);
- cifs_signal_cifsd_for_reconnect(mid->server, false);
+ cifs_signal_cifsd_for_reconnect(server, false);
}
}
diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
index 4670c3e451a75..ee8c3c54a4634 100644
--- a/fs/smb/client/smb1ops.c
+++ b/fs/smb/client/smb1ops.c
@@ -97,7 +97,7 @@ cifs_find_mid(struct TCP_Server_Info *server, char *buffer)
if (compare_mid(mid->mid, buf) &&
mid->mid_state == MID_REQUEST_SUBMITTED &&
le16_to_cpu(mid->command) == buf->Command) {
- kref_get(&mid->refcount);
+ refcount_inc(&mid->refcount);
spin_unlock(&server->mid_lock);
return mid;
}
@@ -398,7 +398,7 @@ cifs_check_trans2(struct mid_q_entry *mid, struct TCP_Server_Info *server,
return true;
/* All parts received or packet is malformed. */
mid->multiEnd = true;
- dequeue_mid(mid, malformed);
+ dequeue_mid(server, mid, malformed);
return true;
}
if (!server->large_buf) {
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index e99b8e1f66d4f..e6e8c64a5d3d6 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -417,7 +417,7 @@ __smb2_find_mid(struct TCP_Server_Info *server, char *buf, bool dequeue)
if ((mid->mid == wire_mid) &&
(mid->mid_state == MID_REQUEST_SUBMITTED) &&
(mid->command == shdr->Command)) {
- kref_get(&mid->refcount);
+ refcount_inc(&mid->refcount);
if (dequeue) {
list_del_init(&mid->qhead);
mid->mid_flags |= MID_DELETED;
@@ -4727,7 +4727,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
if (is_offloaded)
mid->mid_state = MID_RESPONSE_RECEIVED;
else
- dequeue_mid(mid, false);
+ dequeue_mid(server, mid, false);
return 0;
}
@@ -4754,7 +4754,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
if (is_offloaded)
mid->mid_state = MID_RESPONSE_MALFORMED;
else
- dequeue_mid(mid, rdata->result);
+ dequeue_mid(server, mid, rdata->result);
return 0;
}
@@ -4773,7 +4773,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
if (is_offloaded)
mid->mid_state = MID_RESPONSE_MALFORMED;
else
- dequeue_mid(mid, rdata->result);
+ dequeue_mid(server, mid, rdata->result);
return 0;
}
@@ -4783,7 +4783,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
if (is_offloaded)
mid->mid_state = MID_RESPONSE_MALFORMED;
else
- dequeue_mid(mid, rdata->result);
+ dequeue_mid(server, mid, rdata->result);
return 0;
}
@@ -4794,7 +4794,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
if (is_offloaded)
mid->mid_state = MID_RESPONSE_MALFORMED;
else
- dequeue_mid(mid, rdata->result);
+ dequeue_mid(server, mid, rdata->result);
return 0;
}
rdata->got_bytes = data_len;
@@ -4813,14 +4813,14 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
if (is_offloaded)
mid->mid_state = MID_RESPONSE_MALFORMED;
else
- dequeue_mid(mid, rdata->result);
+ dequeue_mid(server, mid, rdata->result);
return 0;
}
if (is_offloaded)
mid->mid_state = MID_RESPONSE_RECEIVED;
else
- dequeue_mid(mid, false);
+ dequeue_mid(server, mid, false);
return 0;
}
@@ -4867,7 +4867,7 @@ static void smb2_decrypt_offload(struct work_struct *work)
dw->server->ops->is_network_name_deleted(dw->buf,
dw->server);
- mid->callback(mid);
+ mid->callback(dw->server, mid);
} else {
spin_lock(&dw->server->srv_lock);
if (dw->server->tcpStatus == CifsNeedReconnect) {
@@ -4875,7 +4875,7 @@ static void smb2_decrypt_offload(struct work_struct *work)
mid->mid_state = MID_RETRY_NEEDED;
spin_unlock(&dw->server->mid_lock);
spin_unlock(&dw->server->srv_lock);
- mid->callback(mid);
+ mid->callback(dw->server, mid);
} else {
spin_lock(&dw->server->mid_lock);
mid->mid_state = MID_REQUEST_SUBMITTED;
@@ -4886,7 +4886,7 @@ static void smb2_decrypt_offload(struct work_struct *work)
spin_unlock(&dw->server->srv_lock);
}
}
- release_mid(mid);
+ release_mid(dw->server, mid);
}
free_pages:
diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
index 5a8a9e4ba36db..bd271d614ed6c 100644
--- a/fs/smb/client/smb2pdu.c
+++ b/fs/smb/client/smb2pdu.c
@@ -4121,9 +4121,8 @@ SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon,
* FIXME: maybe we should consider checking that the reply matches request?
*/
static void
-smb2_echo_callback(struct mid_q_entry *mid)
+smb2_echo_callback(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{
- struct TCP_Server_Info *server = mid->callback_data;
struct smb2_echo_rsp *rsp = (struct smb2_echo_rsp *)mid->resp_buf;
struct cifs_credits credits = { .value = 0, .instance = 0 };
@@ -4133,7 +4132,7 @@ smb2_echo_callback(struct mid_q_entry *mid)
credits.instance = server->reconnect_instance;
}
- release_mid(mid);
+ release_mid(server, mid);
add_credits(server, &credits, CIFS_ECHO_OP);
}
@@ -4537,12 +4536,11 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
}
static void
-smb2_readv_callback(struct mid_q_entry *mid)
+smb2_readv_callback(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{
struct cifs_io_subrequest *rdata = mid->callback_data;
struct netfs_inode *ictx = netfs_inode(rdata->rreq->inode);
struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);
- struct TCP_Server_Info *server = rdata->server;
struct smb2_hdr *shdr =
(struct smb2_hdr *)rdata->iov[0].iov_base;
struct cifs_credits credits = {
@@ -4559,9 +4557,9 @@ smb2_readv_callback(struct mid_q_entry *mid)
rqst.rq_iter = rdata->subreq.io_iter;
}
- WARN_ONCE(rdata->server != mid->server,
+ WARN_ONCE(rdata->server != server,
"rdata server %p != mid server %p",
- rdata->server, mid->server);
+ rdata->server, server);
cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%zu/%zu\n",
__func__, mid->mid, mid->mid_state, rdata->result,
@@ -4652,7 +4650,7 @@ smb2_readv_callback(struct mid_q_entry *mid)
rdata->subreq.transferred += rdata->got_bytes;
trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_progress);
queue_work(cifsiod_wq, &rdata->subreq.work);
- release_mid(mid);
+ release_mid(server, mid);
trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, 0,
server->credits, server->in_flight,
credits.value, cifs_trace_rw_credits_read_response_add);
@@ -4829,11 +4827,10 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
* workqueue completion task.
*/
static void
-smb2_writev_callback(struct mid_q_entry *mid)
+smb2_writev_callback(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{
struct cifs_io_subrequest *wdata = mid->callback_data;
struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);
- struct TCP_Server_Info *server = wdata->server;
struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf;
struct cifs_credits credits = {
.value = 0,
@@ -4846,9 +4843,9 @@ smb2_writev_callback(struct mid_q_entry *mid)
ssize_t result = 0;
size_t written;
- WARN_ONCE(wdata->server != mid->server,
+ WARN_ONCE(wdata->server != server,
"wdata server %p != mid server %p",
- wdata->server, mid->server);
+ wdata->server, server);
switch (mid->mid_state) {
case MID_RESPONSE_RECEIVED:
@@ -4926,7 +4923,7 @@ smb2_writev_callback(struct mid_q_entry *mid)
wdata->credits.value = 0;
trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_progress);
cifs_write_subrequest_terminated(wdata, result ?: written, true);
- release_mid(mid);
+ release_mid(server, mid);
trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, 0,
server->credits, server->in_flight,
credits.value, cifs_trace_rw_credits_write_response_add);
diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c
index 31d22af0c626c..5c0ceb3cc0dd7 100644
--- a/fs/smb/client/smb2transport.c
+++ b/fs/smb/client/smb2transport.c
@@ -792,14 +792,12 @@ smb2_mid_entry_alloc(const struct smb2_hdr *shdr,
temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
memset(temp, 0, sizeof(struct mid_q_entry));
- kref_init(&temp->refcount);
+ refcount_set(&temp->refcount, 1);
temp->mid = le64_to_cpu(shdr->MessageId);
temp->credits = credits > 0 ? credits : 1;
temp->pid = current->pid;
temp->command = shdr->Command; /* Always LE */
temp->when_alloc = jiffies;
- temp->server = server;
-
/*
* The default is for the mid to be synchronous, so the
* default callback just wakes up the current task.
@@ -915,7 +913,7 @@ smb2_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *server,
rc = smb2_sign_rqst(rqst, server);
if (rc) {
revert_current_mid_from_hdr(server, shdr);
- delete_mid(mid);
+ delete_mid(server, mid);
return ERR_PTR(rc);
}
@@ -949,7 +947,7 @@ smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
rc = smb2_sign_rqst(rqst, server);
if (rc) {
revert_current_mid_from_hdr(server, shdr);
- release_mid(mid);
+ release_mid(server, mid);
return ERR_PTR(rc);
}
diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c
index d7dbbd908cd90..68523c94a70f9 100644
--- a/fs/smb/client/transport.c
+++ b/fs/smb/client/transport.c
@@ -35,7 +35,7 @@
#define CIFS_MAX_IOV_SIZE 8
void
-cifs_wake_up_task(struct mid_q_entry *mid)
+cifs_wake_up_task(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{
if (mid->mid_state == MID_RESPONSE_RECEIVED)
mid->mid_state = MID_RESPONSE_READY;
@@ -54,7 +54,7 @@ alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
memset(temp, 0, sizeof(struct mid_q_entry));
- kref_init(&temp->refcount);
+ refcount_set(&temp->refcount, 1);
temp->mid = get_mid(smb_buffer);
temp->pid = current->pid;
temp->command = cpu_to_le16(smb_buffer->Command);
@@ -62,8 +62,6 @@ alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
/* easier to use jiffies */
/* when mid allocated can be before when sent */
temp->when_alloc = jiffies;
- temp->server = server;
-
/*
* The default is for the mid to be synchronous, so the
* default callback just wakes up the current task.
@@ -78,18 +76,15 @@ alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
return temp;
}
-void __release_mid(struct kref *refcount)
+void __release_mid(struct TCP_Server_Info *server,
+ struct mid_q_entry *midEntry)
{
- struct mid_q_entry *midEntry =
- container_of(refcount, struct mid_q_entry, refcount);
#ifdef CONFIG_CIFS_STATS2
- __le16 command = midEntry->server->vals->lock_cmd;
+ __le16 command = server->vals->lock_cmd;
__u16 smb_cmd = le16_to_cpu(midEntry->command);
unsigned long now;
unsigned long roundtrip_time;
#endif
- struct TCP_Server_Info *server = midEntry->server;
-
if (midEntry->resp_buf && (midEntry->mid_flags & MID_WAIT_CANCELLED) &&
(midEntry->mid_state == MID_RESPONSE_RECEIVED ||
midEntry->mid_state == MID_RESPONSE_READY) &&
@@ -159,16 +154,16 @@ void __release_mid(struct kref *refcount)
}
void
-delete_mid(struct mid_q_entry *mid)
+delete_mid(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{
- spin_lock(&mid->server->mid_lock);
+ spin_lock(&server->mid_lock);
if (!(mid->mid_flags & MID_DELETED)) {
list_del_init(&mid->qhead);
mid->mid_flags |= MID_DELETED;
}
- spin_unlock(&mid->server->mid_lock);
+ spin_unlock(&server->mid_lock);
- release_mid(mid);
+ release_mid(server, mid);
}
/*
@@ -780,7 +775,7 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
rc = cifs_sign_rqst(rqst, server, &mid->sequence_number);
if (rc) {
- release_mid(mid);
+ release_mid(server, mid);
return ERR_PTR(rc);
}
@@ -855,7 +850,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst,
if (rc < 0) {
revert_current_mid(server, mid->credits);
server->sequence_number -= 2;
- delete_mid(mid);
+ delete_mid(server, mid);
}
cifs_server_unlock(server);
@@ -930,7 +925,7 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
spin_unlock(&server->mid_lock);
sync_mid_done:
- release_mid(mid);
+ release_mid(server, mid);
return rc;
}
@@ -970,11 +965,11 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
}
/* BB special case reconnect tid and uid here? */
- return map_and_check_smb_error(mid, log_error);
+ return map_and_check_smb_error(server, mid, log_error);
}
struct mid_q_entry *
-cifs_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *ignored,
+cifs_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *server,
struct smb_rqst *rqst)
{
int rc;
@@ -988,18 +983,17 @@ cifs_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *ignored,
rc = allocate_mid(ses, hdr, &mid);
if (rc)
return ERR_PTR(rc);
- rc = cifs_sign_rqst(rqst, ses->server, &mid->sequence_number);
+ rc = cifs_sign_rqst(rqst, server, &mid->sequence_number);
if (rc) {
- delete_mid(mid);
+ delete_mid(server, mid);
return ERR_PTR(rc);
}
return mid;
}
static void
-cifs_compound_callback(struct mid_q_entry *mid)
+cifs_compound_callback(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{
- struct TCP_Server_Info *server = mid->server;
struct cifs_credits credits = {
.value = server->ops->get_credits(mid),
.instance = server->reconnect_instance,
@@ -1012,17 +1006,19 @@ cifs_compound_callback(struct mid_q_entry *mid)
}
static void
-cifs_compound_last_callback(struct mid_q_entry *mid)
+cifs_compound_last_callback(struct TCP_Server_Info *server,
+ struct mid_q_entry *mid)
{
- cifs_compound_callback(mid);
- cifs_wake_up_task(mid);
+ cifs_compound_callback(server, mid);
+ cifs_wake_up_task(server, mid);
}
static void
-cifs_cancelled_callback(struct mid_q_entry *mid)
+cifs_cancelled_callback(struct TCP_Server_Info *server,
+ struct mid_q_entry *mid)
{
- cifs_compound_callback(mid);
- release_mid(mid);
+ cifs_compound_callback(server, mid);
+ release_mid(server, mid);
}
/*
@@ -1155,7 +1151,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
if (IS_ERR(midQ[i])) {
revert_current_mid(server, i);
for (j = 0; j < i; j++)
- delete_mid(midQ[j]);
+ delete_mid(server, midQ[j]);
cifs_server_unlock(server);
/* Update # of requests on wire to server */
@@ -1306,7 +1302,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
*/
for (i = 0; i < num_rqst; i++) {
if (!cancelled_mid[i])
- delete_mid(midQ[i]);
+ delete_mid(server, midQ[i]);
}
return rc;
@@ -1470,7 +1466,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
rc = cifs_check_receive(midQ, server, 0);
out:
- delete_mid(midQ);
+ delete_mid(server, midQ);
add_credits(server, &credits, 0);
return rc;
@@ -1563,7 +1559,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
rc = cifs_sign_smb(in_buf, server, &midQ->sequence_number);
if (rc) {
- delete_mid(midQ);
+ delete_mid(server, midQ);
cifs_server_unlock(server);
return rc;
}
@@ -1578,7 +1574,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
cifs_server_unlock(server);
if (rc < 0) {
- delete_mid(midQ);
+ delete_mid(server, midQ);
return rc;
}
@@ -1603,7 +1599,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
blocking lock to return. */
rc = send_cancel(server, &rqst, midQ);
if (rc) {
- delete_mid(midQ);
+ delete_mid(server, midQ);
return rc;
}
} else {
@@ -1615,7 +1611,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
/* If we get -ENOLCK back the lock may have
already been removed. Don't exit in this case. */
if (rc && rc != -ENOLCK) {
- delete_mid(midQ);
+ delete_mid(server, midQ);
return rc;
}
}
@@ -1655,7 +1651,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
rc = cifs_check_receive(midQ, server, 0);
out:
- delete_mid(midQ);
+ delete_mid(server, midQ);
if (rstart && rc == -EACCES)
return -ERESTARTSYS;
return rc;
@@ -1694,7 +1690,7 @@ __cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid,
int length;
length = cifs_discard_remaining_data(server);
- dequeue_mid(mid, malformed);
+ dequeue_mid(server, mid, malformed);
mid->resp_buf = server->smallbuf;
server->smallbuf = NULL;
return length;
@@ -1837,7 +1833,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
if (server->total_read < buflen)
return cifs_readv_discard(server, mid);
- dequeue_mid(mid, false);
+ dequeue_mid(server, mid, false);
mid->resp_buf = server->smallbuf;
server->smallbuf = NULL;
return length;
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 6.12.y 2/6] cifs: Do some preparation prior to organising the function declarations
2026-09-07 15:00 ` [PATCH 6.12.y 1/6] cifs: Remove the server pointer from smb_message Sasha Levin
@ 2026-09-07 15:00 ` Sasha Levin
2026-09-07 15:00 ` [PATCH 6.12.y 3/6] cifs: Remove dead function prototypes Sasha Levin
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Sasha Levin @ 2026-09-07 15:00 UTC (permalink / raw)
To: stable
Cc: David Howells, Paulo Alcantara (Red Hat), linux-cifs,
Steve French, Sasha Levin
From: David Howells <dhowells@redhat.com>
[ Upstream commit 32a60868093aed5ccaa5e57f3b57f791f22ac133 ]
Make some preparatory cleanups prior to running a script to organise the
function declarations within the fs/smb/client/ headers. These include:
(1) Remove "inline" from the dummy cifs_proc_init/clean() functions as
they are in a .c file.
(2) Move should_compress()'s kdoc comment to the .c file and remove kdoc
markers from the comments.
(3) Rename CIFS_ALLOW_INSECURE_LEGACY in #endif comments to have CONFIG_
on the front to allow the script to recognise it.
(4) Don't let comments have bare words at the left margin as that confused
the simplistic function detection code in the script.
(5) Adjust some argument lists so that when and if the cleanup script is
run they don't end up over 100 chars.
(6) Fix a few comments to have missing '*' added or the "*/" moved to
their own lines so that checkpatch doesn't moan over the cleanup
script patch.
(7) Move struct cifs_calc_sig_ctx to cifsglob.h.
(8) Remove some __KERNEL__ conditionals.
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Paulo Alcantara (Red Hat) <pc@manguebit.org>
cc: linux-cifs@vger.kernel.org
Signed-off-by: Steve French <stfrench@microsoft.com>
Stable-dep-of: 730d0bb19507 ("smb: client: fix UAF and buffer leak in cifs_check_trans2() for malformed secondary T2")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/smb/client/cifs_debug.c | 4 ++--
fs/smb/client/cifs_spnego.h | 2 --
fs/smb/client/cifs_unicode.h | 3 ---
fs/smb/client/cifsfs.c | 5 +++--
fs/smb/client/cifsglob.h | 2 +-
fs/smb/client/cifsproto.h | 2 +-
fs/smb/client/compress.c | 21 ++++++++++++++++++---
fs/smb/client/compress.h | 19 ++-----------------
fs/smb/client/dir.c | 2 +-
fs/smb/client/dns_resolve.h | 3 ---
fs/smb/client/fs_context.c | 2 +-
fs/smb/client/misc.c | 1 +
fs/smb/client/netmisc.c | 2 +-
fs/smb/client/smb2file.c | 3 ++-
fs/smb/client/smb2inode.c | 1 -
fs/smb/client/smb2maperror.c | 3 +--
fs/smb/client/smb2ops.c | 4 ++--
fs/smb/client/smb2pdu.c | 5 +++--
fs/smb/client/smb2proto.h | 2 ++
19 files changed, 41 insertions(+), 45 deletions(-)
diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c
index 9092051776fc1..bd9ebd4368887 100644
--- a/fs/smb/client/cifs_debug.c
+++ b/fs/smb/client/cifs_debug.c
@@ -1209,11 +1209,11 @@ static const struct proc_ops cifs_mount_params_proc_ops = {
};
#else
-inline void cifs_proc_init(void)
+void cifs_proc_init(void)
{
}
-inline void cifs_proc_clean(void)
+void cifs_proc_clean(void)
{
}
#endif /* PROC_FS */
diff --git a/fs/smb/client/cifs_spnego.h b/fs/smb/client/cifs_spnego.h
index e4d751b0c8127..e70929db3611f 100644
--- a/fs/smb/client/cifs_spnego.h
+++ b/fs/smb/client/cifs_spnego.h
@@ -27,10 +27,8 @@ struct cifs_spnego_msg {
uint8_t data[];
};
-#ifdef __KERNEL__
extern struct key_type cifs_spnego_key_type;
extern struct key *cifs_get_spnego_key(struct cifs_ses *sesInfo,
struct TCP_Server_Info *server);
-#endif /* KERNEL */
#endif /* _CIFS_SPNEGO_H */
diff --git a/fs/smb/client/cifs_unicode.h b/fs/smb/client/cifs_unicode.h
index e137a0dfbbe9a..6e4b99786498d 100644
--- a/fs/smb/client/cifs_unicode.h
+++ b/fs/smb/client/cifs_unicode.h
@@ -54,7 +54,6 @@
#define SFM_MAP_UNI_RSVD 1
#define SFU_MAP_UNI_RSVD 2
-#ifdef __KERNEL__
int cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
const struct nls_table *cp, int map_type);
int cifs_utf16_bytes(const __le16 *from, int maxbytes,
@@ -69,8 +68,6 @@ extern int cifs_remap(struct cifs_sb_info *cifs_sb);
extern __le16 *cifs_strndup_to_utf16(const char *src, const int maxlen,
int *utf16_len, const struct nls_table *cp,
int remap);
-#endif
-
wchar_t cifs_toupper(wchar_t in);
#endif /* _CIFS_UNICODE_H */
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
index 08e7931cdda2b..f7cf455b9e124 100644
--- a/fs/smb/client/cifsfs.c
+++ b/fs/smb/client/cifsfs.c
@@ -28,6 +28,8 @@
#include <linux/splice.h>
#include <linux/uuid.h>
#include <linux/xattr.h>
+#include <linux/mm.h>
+#include <linux/key-type.h>
#include <uapi/linux/magic.h>
#include <net/ipv6.h>
#include "cifsfs.h"
@@ -35,10 +37,9 @@
#define DECLARE_GLOBALS_HERE
#include "cifsglob.h"
#include "cifsproto.h"
+#include "smb2proto.h"
#include "cifs_debug.h"
#include "cifs_fs_sb.h"
-#include <linux/mm.h>
-#include <linux/key-type.h>
#include "cifs_spnego.h"
#include "fscache.h"
#ifdef CONFIG_CIFS_DFS_UPCALL
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index d61a6424f20ca..13b01a90c2ea4 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -2065,7 +2065,7 @@ extern struct smb_version_operations smb1_operations;
extern struct smb_version_values smb1_values;
extern struct smb_version_operations smb20_operations;
extern struct smb_version_values smb20_values;
-#endif /* CIFS_ALLOW_INSECURE_LEGACY */
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
extern struct smb_version_operations smb21_operations;
extern struct smb_version_values smb21_values;
extern struct smb_version_values smbdefault_values;
diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
index 5f28eee91eb9d..7965a751d35c0 100644
--- a/fs/smb/client/cifsproto.h
+++ b/fs/smb/client/cifsproto.h
@@ -595,7 +595,7 @@ extern int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
const struct nls_table *nls_codepage, int remap);
extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
-#endif /* CIFS_ALLOW_INSECURE_LEGACY */
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
extern bool couldbe_mf_symlink(const struct cifs_fattr *fattr);
extern int check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
diff --git a/fs/smb/client/compress.c b/fs/smb/client/compress.c
index db709f5cd2e1f..fb2a48f1d2ad0 100644
--- a/fs/smb/client/compress.c
+++ b/fs/smb/client/compress.c
@@ -44,7 +44,7 @@ struct bucket {
unsigned int count;
};
-/**
+/*
* has_low_entropy() - Compute Shannon entropy of the sampled data.
* @bkt: Bytes counts of the sample.
* @slen: Size of the sample.
@@ -82,7 +82,7 @@ static bool has_low_entropy(struct bucket *bkt, size_t slen)
#define BYTE_DIST_BAD 0
#define BYTE_DIST_GOOD 1
#define BYTE_DIST_MAYBE 2
-/**
+/*
* calc_byte_distribution() - Compute byte distribution on the sampled data.
* @bkt: Byte counts of the sample.
* @slen: Size of the sample.
@@ -182,7 +182,7 @@ static int collect_sample(const struct iov_iter *source, ssize_t max, u8 *sample
return s;
}
-/**
+/*
* is_compressible() - Determines if a chunk of data is compressible.
* @data: Iterator containing uncompressed data.
*
@@ -261,6 +261,21 @@ static bool is_compressible(const struct iov_iter *data)
return ret;
}
+/*
+ * should_compress() - Determines if a request (write) or the response to a
+ * request (read) should be compressed.
+ * @tcon: tcon of the request is being sent to
+ * @rqst: request to evaluate
+ *
+ * Return: true iff:
+ * - compression was successfully negotiated with server
+ * - server has enabled compression for the share
+ * - it's a read or write request
+ * - (write only) request length is >= SMB_COMPRESS_MIN_LEN
+ * - (write only) is_compressible() returns 1
+ *
+ * Return false otherwise.
+ */
bool should_compress(const struct cifs_tcon *tcon, const struct smb_rqst *rq)
{
const struct smb2_hdr *shdr = rq->rq_iov->iov_base;
diff --git a/fs/smb/client/compress.h b/fs/smb/client/compress.h
index f3ed1d3e52fbf..63aea32fbe921 100644
--- a/fs/smb/client/compress.h
+++ b/fs/smb/client/compress.h
@@ -29,26 +29,11 @@
#ifdef CONFIG_CIFS_COMPRESSION
typedef int (*compress_send_fn)(struct TCP_Server_Info *, int, struct smb_rqst *);
-int smb_compress(struct TCP_Server_Info *server, struct smb_rqst *rq, compress_send_fn send_fn);
-/**
- * should_compress() - Determines if a request (write) or the response to a
- * request (read) should be compressed.
- * @tcon: tcon of the request is being sent to
- * @rqst: request to evaluate
- *
- * Return: true iff:
- * - compression was successfully negotiated with server
- * - server has enabled compression for the share
- * - it's a read or write request
- * - (write only) request length is >= SMB_COMPRESS_MIN_LEN
- * - (write only) is_compressible() returns 1
- *
- * Return false otherwise.
- */
+int smb_compress(struct TCP_Server_Info *server, struct smb_rqst *rq, compress_send_fn send_fn);
bool should_compress(const struct cifs_tcon *tcon, const struct smb_rqst *rq);
-/**
+/*
* smb_compress_alg_valid() - Validate a compression algorithm.
* @alg: Compression algorithm to check.
* @valid_none: Conditional check whether NONE algorithm should be
diff --git a/fs/smb/client/dir.c b/fs/smb/client/dir.c
index 6bb0e98462a98..7c528dec4149e 100644
--- a/fs/smb/client/dir.c
+++ b/fs/smb/client/dir.c
@@ -432,7 +432,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
int
cifs_atomic_open(struct inode *inode, struct dentry *direntry,
- struct file *file, unsigned oflags, umode_t mode)
+ struct file *file, unsigned int oflags, umode_t mode)
{
int rc;
unsigned int xid;
diff --git a/fs/smb/client/dns_resolve.h b/fs/smb/client/dns_resolve.h
index 6eb0c15a24406..2e991cdd2f496 100644
--- a/fs/smb/client/dns_resolve.h
+++ b/fs/smb/client/dns_resolve.h
@@ -13,8 +13,5 @@
#include <linux/net.h>
-#ifdef __KERNEL__
int dns_resolve_server_name_to_ip(const char *unc, struct sockaddr *ip_addr, time64_t *expiry);
-#endif /* KERNEL */
-
#endif /* _DNS_RESOLVE_H */
diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
index 769380020d41a..37665788f62bf 100644
--- a/fs/smb/client/fs_context.c
+++ b/fs/smb/client/fs_context.c
@@ -443,7 +443,7 @@ cifs_parse_smb_version(struct fs_context *fc, char *value, struct smb3_fs_contex
case Smb_20:
cifs_errorf(fc, "vers=2.0 mount not permitted when legacy dialects disabled\n");
return 1;
-#endif /* CIFS_ALLOW_INSECURE_LEGACY */
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
case Smb_21:
ctx->ops = &smb21_operations;
ctx->vals = &smb21_values;
diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c
index ce8f3fdffc3bd..f7b842eac044e 100644
--- a/fs/smb/client/misc.c
+++ b/fs/smb/client/misc.c
@@ -18,6 +18,7 @@
#include "nterr.h"
#include "cifs_unicode.h"
#include "smb2pdu.h"
+#include "smb2proto.h"
#include "cifsfs.h"
#ifdef CONFIG_CIFS_DFS_UPCALL
#include "dns_resolve.h"
diff --git a/fs/smb/client/netmisc.c b/fs/smb/client/netmisc.c
index 8db57bd1a39de..407bafe6dc2ef 100644
--- a/fs/smb/client/netmisc.c
+++ b/fs/smb/client/netmisc.c
@@ -200,7 +200,7 @@ cifs_set_port(struct sockaddr *addr, const unsigned short int port)
}
/*****************************************************************************
-convert a NT status code to a dos class/code
+ *convert a NT status code to a dos class/code
*****************************************************************************/
/* NT status -> dos error map */
static const struct {
diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c
index 279aaa755106a..e1bc36c0dc951 100644
--- a/fs/smb/client/smb2file.c
+++ b/fs/smb/client/smb2file.c
@@ -102,7 +102,8 @@ int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb, const struct kvec
cifs_sb);
}
-int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock, void *buf)
+int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
+ __u32 *oplock, void *buf)
{
int rc;
__le16 *smb2_path;
diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
index 4f08c808e4a3e..a85fc7354b613 100644
--- a/fs/smb/client/smb2inode.c
+++ b/fs/smb/client/smb2inode.c
@@ -21,7 +21,6 @@
#include "cifs_unicode.h"
#include "fscache.h"
#include "smb2glob.h"
-#include "smb2pdu.h"
#include "smb2proto.h"
#include "cached_dir.h"
#include "../common/smb2status.h"
diff --git a/fs/smb/client/smb2maperror.c b/fs/smb/client/smb2maperror.c
index b05313acf9b2b..43a2f4be494b2 100644
--- a/fs/smb/client/smb2maperror.c
+++ b/fs/smb/client/smb2maperror.c
@@ -10,10 +10,9 @@
#include <linux/errno.h>
#include "cifsglob.h"
#include "cifs_debug.h"
-#include "smb2pdu.h"
#include "smb2proto.h"
-#include "../common/smb2status.h"
#include "smb2glob.h"
+#include "../common/smb2status.h"
#include "trace.h"
struct status_to_posix_error {
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index e6e8c64a5d3d6..06c6d431c6123 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -17,9 +17,9 @@
#include <uapi/linux/magic.h>
#include "cifsfs.h"
#include "cifsglob.h"
-#include "smb2pdu.h"
-#include "smb2proto.h"
#include "cifsproto.h"
+#include "smb2proto.h"
+#include "smb2pdu.h"
#include "cifs_debug.h"
#include "cifs_unicode.h"
#include "../common/smb2status.h"
diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
index bd271d614ed6c..bb409d3ec454f 100644
--- a/fs/smb/client/smb2pdu.c
+++ b/fs/smb/client/smb2pdu.c
@@ -26,8 +26,8 @@
#include <linux/netfs.h>
#include <trace/events/netfs.h>
#include "cifsglob.h"
-#include "cifsacl.h"
#include "cifsproto.h"
+#include "cifsacl.h"
#include "smb2proto.h"
#include "cifs_unicode.h"
#include "cifs_debug.h"
@@ -3939,7 +3939,8 @@ int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
/* currently unused, as now we are doing compounding instead (see smb311_posix_query_path_info) */
int
SMB311_posix_query_info(const unsigned int xid, struct cifs_tcon *tcon,
- u64 persistent_fid, u64 volatile_fid, struct smb311_posix_qinfo *data, u32 *plen)
+ u64 persistent_fid, u64 volatile_fid,
+ struct smb311_posix_qinfo *data, u32 *plen)
{
size_t output_len = sizeof(struct smb311_posix_qinfo) +
(sizeof(struct smb_sid) * 2) + (PATH_MAX * 2);
diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h
index 51d890f74e36f..c0d9728977e80 100644
--- a/fs/smb/client/smb2proto.h
+++ b/fs/smb/client/smb2proto.h
@@ -9,8 +9,10 @@
*/
#ifndef _SMB2PROTO_H
#define _SMB2PROTO_H
+
#include <linux/nls.h>
#include <linux/key-type.h>
+#include "cached_dir.h"
struct statfs;
struct smb_rqst;
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 6.12.y 3/6] cifs: Remove dead function prototypes
2026-09-07 15:00 ` [PATCH 6.12.y 1/6] cifs: Remove the server pointer from smb_message Sasha Levin
2026-09-07 15:00 ` [PATCH 6.12.y 2/6] cifs: Do some preparation prior to organising the function declarations Sasha Levin
@ 2026-09-07 15:00 ` Sasha Levin
2026-09-07 15:00 ` [PATCH 6.12.y 4/6] cifs: Scripted clean up fs/smb/client/fscache.h Sasha Levin
2026-09-07 15:00 ` [PATCH 6.12.y 5/6] cifs: SMB1 split: Create smb1proto.h for SMB1 declarations Sasha Levin
3 siblings, 0 replies; 5+ messages in thread
From: Sasha Levin @ 2026-09-07 15:00 UTC (permalink / raw)
To: stable
Cc: David Howells, linux-cifs, linux-fsdevel,
Paulo Alcantara (Red Hat), Steve French, Sasha Levin
From: David Howells <dhowells@redhat.com>
[ Upstream commit 9146c7e53fa8e5024e0f61d67129afd45a179a3b ]
Remove a bunch of dead function prototypes.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: linux-cifs@vger.kernel.org
cc: linux-fsdevel@vger.kernel.org
Reviewed-by: Paulo Alcantara (Red Hat) <pc@manguebit.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Stable-dep-of: 730d0bb19507 ("smb: client: fix UAF and buffer leak in cifs_check_trans2() for malformed secondary T2")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/smb/client/cifsproto.h | 6 ------
fs/smb/client/smb2proto.h | 12 ------------
2 files changed, 18 deletions(-)
diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
index 7965a751d35c0..1f71a0977469f 100644
--- a/fs/smb/client/cifsproto.h
+++ b/fs/smb/client/cifsproto.h
@@ -81,7 +81,6 @@ extern char *cifs_build_path_to_root(struct smb3_fs_context *ctx,
struct cifs_sb_info *cifs_sb,
struct cifs_tcon *tcon,
int add_treename);
-extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
char *cifs_build_devname(char *nodename, const char *prepath);
extern void delete_mid(struct TCP_Server_Info *server, struct mid_q_entry *mid);
void __release_mid(struct TCP_Server_Info *server, struct mid_q_entry *mid);
@@ -151,8 +150,6 @@ extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *);
extern bool backup_cred(struct cifs_sb_info *);
extern bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 eof,
bool from_readdir);
-extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
- unsigned int bytes_written);
void cifs_write_subrequest_terminated(struct cifs_io_subrequest *wdata, ssize_t result,
bool was_async);
extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, int);
@@ -181,8 +178,6 @@ extern void header_assemble(struct smb_hdr *, char /* command */ ,
extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
struct cifs_ses *ses,
void **request_buf);
-extern enum securityEnum select_sectype(struct TCP_Server_Info *server,
- enum securityEnum requested);
extern int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
struct TCP_Server_Info *server,
const struct nls_table *nls_cp);
@@ -639,7 +634,6 @@ int cifs_try_adding_channels(struct cifs_ses *ses);
bool is_server_using_iface(struct TCP_Server_Info *server,
struct cifs_server_iface *iface);
bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface);
-void cifs_ses_mark_for_reconnect(struct cifs_ses *ses);
int
cifs_ses_get_chan_index(struct cifs_ses *ses,
diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h
index c0d9728977e80..20cf8a739559c 100644
--- a/fs/smb/client/smb2proto.h
+++ b/fs/smb/client/smb2proto.h
@@ -47,15 +47,11 @@ extern int smb2_calc_signature(struct smb_rqst *rqst,
extern int smb3_calc_signature(struct smb_rqst *rqst,
struct TCP_Server_Info *server,
bool allocate_crypto);
-extern void smb2_echo_request(struct work_struct *work);
extern __le32 smb2_get_lease_state(struct cifsInodeInfo *cinode);
extern bool smb2_is_valid_oplock_break(char *buffer,
struct TCP_Server_Info *srv);
extern int smb3_handle_read_data(struct TCP_Server_Info *server,
struct mid_q_entry *mid);
-extern int smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, const char *path,
- __u32 *reparse_tag);
struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
struct super_block *sb,
const unsigned int xid,
@@ -310,19 +306,11 @@ extern int smb2_query_info_compound(const unsigned int xid,
struct kvec *rsp, int *buftype,
struct cifs_sb_info *cifs_sb);
/* query path info from the server using SMB311 POSIX extensions*/
-int smb311_posix_query_path_info(const unsigned int xid,
- struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb,
- const char *full_path,
- struct cifs_open_info_data *data);
int posix_info_parse(const void *beg, const void *end,
struct smb2_posix_info_parsed *out);
int posix_info_sid_size(const void *beg, const void *end);
int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
struct dentry *dentry, struct cifs_tcon *tcon,
const char *full_path, const char *symname);
-int smb2_make_nfs_node(unsigned int xid, struct inode *inode,
- struct dentry *dentry, struct cifs_tcon *tcon,
- const char *full_path, umode_t mode, dev_t dev);
#endif /* _SMB2PROTO_H */
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 6.12.y 4/6] cifs: Scripted clean up fs/smb/client/fscache.h
2026-09-07 15:00 ` [PATCH 6.12.y 1/6] cifs: Remove the server pointer from smb_message Sasha Levin
2026-09-07 15:00 ` [PATCH 6.12.y 2/6] cifs: Do some preparation prior to organising the function declarations Sasha Levin
2026-09-07 15:00 ` [PATCH 6.12.y 3/6] cifs: Remove dead function prototypes Sasha Levin
@ 2026-09-07 15:00 ` Sasha Levin
2026-09-07 15:00 ` [PATCH 6.12.y 5/6] cifs: SMB1 split: Create smb1proto.h for SMB1 declarations Sasha Levin
3 siblings, 0 replies; 5+ messages in thread
From: Sasha Levin @ 2026-09-07 15:00 UTC (permalink / raw)
To: stable
Cc: David Howells, Steve French, Paulo Alcantara, Enzo Matsumiya,
linux-cifs, linux-fsdevel, linux-kernel, Steve French,
Sasha Levin
From: David Howells <dhowells@redhat.com>
[ Upstream commit bc3de356aae666de5d8b5131545be87cf7754431 ]
Remove externs, correct argument names and reformat declarations.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Steve French <sfrench@samba.org>
cc: Paulo Alcantara <pc@manguebit.org>
cc: Enzo Matsumiya <ematsumiya@suse.de>
cc: linux-cifs@vger.kernel.org
cc: linux-fsdevel@vger.kernel.org
cc: linux-kernel@vger.kernel.org
Acked-by: Enzo Matsumiya <ematsumiya@suse.de>
Signed-off-by: Steve French <stfrench@microsoft.com>
Stable-dep-of: 730d0bb19507 ("smb: client: fix UAF and buffer leak in cifs_check_trans2() for malformed secondary T2")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/smb/client/fscache.h | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/fs/smb/client/fscache.h b/fs/smb/client/fscache.h
index f06cb24f5f3cf..b6c94db5edb94 100644
--- a/fs/smb/client/fscache.h
+++ b/fs/smb/client/fscache.h
@@ -38,12 +38,12 @@ struct cifs_fscache_inode_coherency_data {
/*
* fscache.c
*/
-extern int cifs_fscache_get_super_cookie(struct cifs_tcon *);
-extern void cifs_fscache_release_super_cookie(struct cifs_tcon *);
+int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon);
+void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon);
-extern void cifs_fscache_get_inode_cookie(struct inode *inode);
-extern void cifs_fscache_release_inode_cookie(struct inode *);
-extern void cifs_fscache_unuse_inode_cookie(struct inode *inode, bool update);
+void cifs_fscache_get_inode_cookie(struct inode *inode);
+void cifs_fscache_release_inode_cookie(struct inode *inode);
+void cifs_fscache_unuse_inode_cookie(struct inode *inode, bool update);
static inline
void cifs_fscache_fill_coherency(struct inode *inode,
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 6.12.y 5/6] cifs: SMB1 split: Create smb1proto.h for SMB1 declarations
2026-09-07 15:00 ` [PATCH 6.12.y 1/6] cifs: Remove the server pointer from smb_message Sasha Levin
` (2 preceding siblings ...)
2026-09-07 15:00 ` [PATCH 6.12.y 4/6] cifs: Scripted clean up fs/smb/client/fscache.h Sasha Levin
@ 2026-09-07 15:00 ` Sasha Levin
3 siblings, 0 replies; 5+ messages in thread
From: Sasha Levin @ 2026-09-07 15:00 UTC (permalink / raw)
To: stable
Cc: David Howells, Steve French, Paulo Alcantara, Enzo Matsumiya,
linux-cifs, linux-fsdevel, linux-kernel, Steve French,
Sasha Levin
From: David Howells <dhowells@redhat.com>
[ Upstream commit 86c666506ea2c42649879eeac7f29e7bedef2f23 ]
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Steve French <sfrench@samba.org>
cc: Paulo Alcantara <pc@manguebit.org>
cc: Enzo Matsumiya <ematsumiya@suse.de>
cc: linux-cifs@vger.kernel.org
cc: linux-fsdevel@vger.kernel.org
cc: linux-kernel@vger.kernel.org
Acked-by: Enzo Matsumiya <ematsumiya@suse.de>
Signed-off-by: Steve French <stfrench@microsoft.com>
For the stable backport, also move the existing TRANS2 receive helpers to
smb1transport.c. This mirrors the later upstream code motion needed for the
fix being unblocked while retaining the stable implementation unchanged.
Stable-dep-of: 730d0bb19507 ("smb: client: fix UAF and buffer leak in cifs_check_trans2() for malformed secondary T2")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/smb/client/Makefile | 2 +-
fs/smb/client/cifsglob.h | 2 -
fs/smb/client/cifsproto.h | 11 +-
fs/smb/client/smb1ops.c | 171 -------------------------------
fs/smb/client/smb1proto.h | 40 ++++++++
fs/smb/client/smb1transport.c | 185 ++++++++++++++++++++++++++++++++++
6 files changed, 227 insertions(+), 184 deletions(-)
create mode 100644 fs/smb/client/smb1proto.h
create mode 100644 fs/smb/client/smb1transport.c
diff --git a/fs/smb/client/Makefile b/fs/smb/client/Makefile
index 22023e30915b9..2a84c49679d51 100644
--- a/fs/smb/client/Makefile
+++ b/fs/smb/client/Makefile
@@ -32,6 +32,6 @@ cifs-$(CONFIG_CIFS_SMB_DIRECT) += smbdirect.o
cifs-$(CONFIG_CIFS_ROOT) += cifsroot.o
-cifs-$(CONFIG_CIFS_ALLOW_INSECURE_LEGACY) += smb1ops.o cifssmb.o
+cifs-$(CONFIG_CIFS_ALLOW_INSECURE_LEGACY) += smb1ops.o smb1transport.o cifssmb.o
cifs-$(CONFIG_CIFS_COMPRESSION) += compress.o compress/lz77.o
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index 13b01a90c2ea4..914238a259890 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -2061,8 +2061,6 @@ extern mempool_t cifs_io_subrequest_pool;
/* Operations for different SMB versions */
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
-extern struct smb_version_operations smb1_operations;
-extern struct smb_version_values smb1_values;
extern struct smb_version_operations smb20_operations;
extern struct smb_version_values smb20_values;
#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
index 1f71a0977469f..2d7eef770d0c2 100644
--- a/fs/smb/client/cifsproto.h
+++ b/fs/smb/client/cifsproto.h
@@ -13,6 +13,7 @@
#ifdef CONFIG_CIFS_DFS_UPCALL
#include "dfs_cache.h"
#endif
+#include "smb1proto.h"
struct statfs;
struct smb_rqst;
@@ -419,16 +420,6 @@ extern int CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
struct cifsFileInfo *cfile, __u64 size,
bool set_allocation);
-struct cifs_unix_set_info_args {
- __u64 ctime;
- __u64 atime;
- __u64 mtime;
- __u64 mode;
- kuid_t uid;
- kgid_t gid;
- dev_t device;
-};
-
extern int CIFSSMBUnixSetFileInfo(const unsigned int xid,
struct cifs_tcon *tcon,
const struct cifs_unix_set_info_args *args,
diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
index ee8c3c54a4634..d570c945f1877 100644
--- a/fs/smb/client/smb1ops.c
+++ b/fs/smb/client/smb1ops.c
@@ -234,146 +234,6 @@ cifs_get_next_mid(struct TCP_Server_Info *server)
return mid;
}
-/*
- return codes:
- 0 not a transact2, or all data present
- >0 transact2 with that much data missing
- -EINVAL invalid transact2
- */
-static int
-check2ndT2(char *buf)
-{
- struct smb_hdr *pSMB = (struct smb_hdr *)buf;
- struct smb_t2_rsp *pSMBt;
- int remaining;
- __u16 total_data_size, data_in_this_rsp;
-
- if (pSMB->Command != SMB_COM_TRANSACTION2)
- return 0;
-
- /* check for plausible wct, bcc and t2 data and parm sizes */
- /* check for parm and data offset going beyond end of smb */
- if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
- cifs_dbg(FYI, "Invalid transact2 word count\n");
- return -EINVAL;
- }
-
- pSMBt = (struct smb_t2_rsp *)pSMB;
-
- total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
- data_in_this_rsp = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
-
- if (total_data_size == data_in_this_rsp)
- return 0;
- else if (total_data_size < data_in_this_rsp) {
- cifs_dbg(FYI, "total data %d smaller than data in frame %d\n",
- total_data_size, data_in_this_rsp);
- return -EINVAL;
- }
-
- remaining = total_data_size - data_in_this_rsp;
-
- cifs_dbg(FYI, "missing %d bytes from transact2, check next response\n",
- remaining);
- if (total_data_size > CIFSMaxBufSize) {
- cifs_dbg(VFS, "TotalDataSize %d is over maximum buffer %d\n",
- total_data_size, CIFSMaxBufSize);
- return -EINVAL;
- }
- return remaining;
-}
-
-static int
-coalesce_t2(char *second_buf, struct smb_hdr *target_hdr)
-{
- struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)second_buf;
- struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)target_hdr;
- char *data_area_of_tgt;
- char *data_area_of_src;
- int remaining;
- unsigned int byte_count, total_in_tgt;
- __u16 tgt_total_cnt, src_total_cnt, total_in_src;
-
- src_total_cnt = get_unaligned_le16(&pSMBs->t2_rsp.TotalDataCount);
- tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
-
- if (tgt_total_cnt != src_total_cnt)
- cifs_dbg(FYI, "total data count of primary and secondary t2 differ source=%hu target=%hu\n",
- src_total_cnt, tgt_total_cnt);
-
- total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
-
- remaining = tgt_total_cnt - total_in_tgt;
-
- if (remaining < 0) {
- cifs_dbg(FYI, "Server sent too much data. tgt_total_cnt=%hu total_in_tgt=%u\n",
- tgt_total_cnt, total_in_tgt);
- return -EPROTO;
- }
-
- if (remaining == 0) {
- /* nothing to do, ignore */
- cifs_dbg(FYI, "no more data remains\n");
- return 0;
- }
-
- total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount);
- if (remaining < total_in_src)
- cifs_dbg(FYI, "transact2 2nd response contains too much data\n");
-
- /* find end of first SMB data area */
- data_area_of_tgt = (char *)&pSMBt->hdr.Protocol +
- get_unaligned_le16(&pSMBt->t2_rsp.DataOffset);
-
- /* validate target area */
- data_area_of_src = (char *)&pSMBs->hdr.Protocol +
- get_unaligned_le16(&pSMBs->t2_rsp.DataOffset);
-
- data_area_of_tgt += total_in_tgt;
-
- total_in_tgt += total_in_src;
- /* is the result too big for the field? */
- if (total_in_tgt > USHRT_MAX) {
- cifs_dbg(FYI, "coalesced DataCount too large (%u)\n",
- total_in_tgt);
- return -EPROTO;
- }
- put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount);
-
- /* fix up the BCC */
- byte_count = get_bcc(target_hdr);
- byte_count += total_in_src;
- /* is the result too big for the field? */
- if (byte_count > USHRT_MAX) {
- cifs_dbg(FYI, "coalesced BCC too large (%u)\n", byte_count);
- return -EPROTO;
- }
- put_bcc(byte_count, target_hdr);
-
- byte_count = be32_to_cpu(target_hdr->smb_buf_length);
- byte_count += total_in_src;
- /* don't allow buffer to overflow */
- if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
- cifs_dbg(FYI, "coalesced BCC exceeds buffer size (%u)\n",
- byte_count);
- return -ENOBUFS;
- }
- target_hdr->smb_buf_length = cpu_to_be32(byte_count);
-
- /* copy second buffer into end of first buffer */
- memcpy(data_area_of_tgt, data_area_of_src, total_in_src);
-
- if (remaining != total_in_src) {
- /* more responses to go */
- cifs_dbg(FYI, "waiting for more secondary responses\n");
- return 1;
- }
-
- /* we are done */
- cifs_dbg(FYI, "found the last secondary response\n");
- return 0;
-}
-
static void
cifs_downgrade_oplock(struct TCP_Server_Info *server,
struct cifsInodeInfo *cinode, __u32 oplock,
@@ -382,37 +242,6 @@ cifs_downgrade_oplock(struct TCP_Server_Info *server,
cifs_set_oplock_level(cinode, oplock);
}
-static bool
-cifs_check_trans2(struct mid_q_entry *mid, struct TCP_Server_Info *server,
- char *buf, int malformed)
-{
- if (malformed)
- return false;
- if (check2ndT2(buf) <= 0)
- return false;
- mid->multiRsp = true;
- if (mid->resp_buf) {
- /* merge response - fix up 1st*/
- malformed = coalesce_t2(buf, mid->resp_buf);
- if (malformed > 0)
- return true;
- /* All parts received or packet is malformed. */
- mid->multiEnd = true;
- dequeue_mid(server, mid, malformed);
- return true;
- }
- if (!server->large_buf) {
- /*FIXME: switch to already allocated largebuf?*/
- cifs_dbg(VFS, "1st trans2 resp needs bigbuf\n");
- } else {
- /* Have first buffer */
- mid->resp_buf = buf;
- mid->large_buf = true;
- server->bigbuf = NULL;
- }
- return true;
-}
-
static bool
cifs_need_neg(struct TCP_Server_Info *server)
{
diff --git a/fs/smb/client/smb1proto.h b/fs/smb/client/smb1proto.h
new file mode 100644
index 0000000000000..8dfc6976ceba1
--- /dev/null
+++ b/fs/smb/client/smb1proto.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ *
+ * Copyright (c) International Business Machines Corp., 2002,2008
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ */
+#ifndef _SMB1PROTO_H
+#define _SMB1PROTO_H
+
+struct cifs_unix_set_info_args {
+ __u64 ctime;
+ __u64 atime;
+ __u64 mtime;
+ __u64 mode;
+ kuid_t uid;
+ kgid_t gid;
+ dev_t device;
+};
+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+
+/*
+ * cifssmb.c
+ */
+
+/*
+ * smb1ops.c
+ */
+extern struct smb_version_operations smb1_operations;
+extern struct smb_version_values smb1_values;
+
+/*
+ * smb1transport.c
+ */
+bool cifs_check_trans2(struct mid_q_entry *mid, struct TCP_Server_Info *server,
+ char *buf, int malformed);
+
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+#endif /* _SMB1PROTO_H */
diff --git a/fs/smb/client/smb1transport.c b/fs/smb/client/smb1transport.c
new file mode 100644
index 0000000000000..8e66a2d21f406
--- /dev/null
+++ b/fs/smb/client/smb1transport.c
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * SMB1 transport operations
+ *
+ * Copyright (c) 2012, Jeff Layton <jlayton@redhat.com>
+ */
+
+#include <linux/pagemap.h>
+#include <linux/vfs.h>
+#include <uapi/linux/magic.h>
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifspdu.h"
+
+/*
+ return codes:
+ 0 not a transact2, or all data present
+ >0 transact2 with that much data missing
+ -EINVAL invalid transact2
+ */
+static int
+check2ndT2(char *buf)
+{
+ struct smb_hdr *pSMB = (struct smb_hdr *)buf;
+ struct smb_t2_rsp *pSMBt;
+ int remaining;
+ __u16 total_data_size, data_in_this_rsp;
+
+ if (pSMB->Command != SMB_COM_TRANSACTION2)
+ return 0;
+
+ /* check for plausible wct, bcc and t2 data and parm sizes */
+ /* check for parm and data offset going beyond end of smb */
+ if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
+ cifs_dbg(FYI, "Invalid transact2 word count\n");
+ return -EINVAL;
+ }
+
+ pSMBt = (struct smb_t2_rsp *)pSMB;
+
+ total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
+ data_in_this_rsp = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
+
+ if (total_data_size == data_in_this_rsp)
+ return 0;
+ else if (total_data_size < data_in_this_rsp) {
+ cifs_dbg(FYI, "total data %d smaller than data in frame %d\n",
+ total_data_size, data_in_this_rsp);
+ return -EINVAL;
+ }
+
+ remaining = total_data_size - data_in_this_rsp;
+
+ cifs_dbg(FYI, "missing %d bytes from transact2, check next response\n",
+ remaining);
+ if (total_data_size > CIFSMaxBufSize) {
+ cifs_dbg(VFS, "TotalDataSize %d is over maximum buffer %d\n",
+ total_data_size, CIFSMaxBufSize);
+ return -EINVAL;
+ }
+ return remaining;
+}
+
+static int
+coalesce_t2(char *second_buf, struct smb_hdr *target_hdr)
+{
+ struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)second_buf;
+ struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)target_hdr;
+ char *data_area_of_tgt;
+ char *data_area_of_src;
+ int remaining;
+ unsigned int byte_count, total_in_tgt;
+ __u16 tgt_total_cnt, src_total_cnt, total_in_src;
+
+ src_total_cnt = get_unaligned_le16(&pSMBs->t2_rsp.TotalDataCount);
+ tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
+
+ if (tgt_total_cnt != src_total_cnt)
+ cifs_dbg(FYI, "total data count of primary and secondary t2 differ source=%hu target=%hu\n",
+ src_total_cnt, tgt_total_cnt);
+
+ total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
+
+ remaining = tgt_total_cnt - total_in_tgt;
+
+ if (remaining < 0) {
+ cifs_dbg(FYI, "Server sent too much data. tgt_total_cnt=%hu total_in_tgt=%u\n",
+ tgt_total_cnt, total_in_tgt);
+ return -EPROTO;
+ }
+
+ if (remaining == 0) {
+ /* nothing to do, ignore */
+ cifs_dbg(FYI, "no more data remains\n");
+ return 0;
+ }
+
+ total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount);
+ if (remaining < total_in_src)
+ cifs_dbg(FYI, "transact2 2nd response contains too much data\n");
+
+ /* find end of first SMB data area */
+ data_area_of_tgt = (char *)&pSMBt->hdr.Protocol +
+ get_unaligned_le16(&pSMBt->t2_rsp.DataOffset);
+
+ /* validate target area */
+ data_area_of_src = (char *)&pSMBs->hdr.Protocol +
+ get_unaligned_le16(&pSMBs->t2_rsp.DataOffset);
+
+ data_area_of_tgt += total_in_tgt;
+
+ total_in_tgt += total_in_src;
+ /* is the result too big for the field? */
+ if (total_in_tgt > USHRT_MAX) {
+ cifs_dbg(FYI, "coalesced DataCount too large (%u)\n",
+ total_in_tgt);
+ return -EPROTO;
+ }
+ put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount);
+
+ /* fix up the BCC */
+ byte_count = get_bcc(target_hdr);
+ byte_count += total_in_src;
+ /* is the result too big for the field? */
+ if (byte_count > USHRT_MAX) {
+ cifs_dbg(FYI, "coalesced BCC too large (%u)\n", byte_count);
+ return -EPROTO;
+ }
+ put_bcc(byte_count, target_hdr);
+
+ byte_count = be32_to_cpu(target_hdr->smb_buf_length);
+ byte_count += total_in_src;
+ /* don't allow buffer to overflow */
+ if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
+ cifs_dbg(FYI, "coalesced BCC exceeds buffer size (%u)\n",
+ byte_count);
+ return -ENOBUFS;
+ }
+ target_hdr->smb_buf_length = cpu_to_be32(byte_count);
+
+ /* copy second buffer into end of first buffer */
+ memcpy(data_area_of_tgt, data_area_of_src, total_in_src);
+
+ if (remaining != total_in_src) {
+ /* more responses to go */
+ cifs_dbg(FYI, "waiting for more secondary responses\n");
+ return 1;
+ }
+
+ /* we are done */
+ cifs_dbg(FYI, "found the last secondary response\n");
+ return 0;
+}
+
+bool
+cifs_check_trans2(struct mid_q_entry *mid, struct TCP_Server_Info *server,
+ char *buf, int malformed)
+{
+ if (malformed)
+ return false;
+ if (check2ndT2(buf) <= 0)
+ return false;
+ mid->multiRsp = true;
+ if (mid->resp_buf) {
+ /* merge response - fix up 1st*/
+ malformed = coalesce_t2(buf, mid->resp_buf);
+ if (malformed > 0)
+ return true;
+ /* All parts received or packet is malformed. */
+ mid->multiEnd = true;
+ dequeue_mid(server, mid, malformed);
+ return true;
+ }
+ if (!server->large_buf) {
+ /*FIXME: switch to already allocated largebuf?*/
+ cifs_dbg(VFS, "1st trans2 resp needs bigbuf\n");
+ } else {
+ /* Have first buffer */
+ mid->resp_buf = buf;
+ mid->large_buf = true;
+ server->bigbuf = NULL;
+ }
+ return true;
+}
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-09-07 15:01 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <2026090303-ashamed-silver-ed5c@gregkh>
2026-09-07 15:00 ` [PATCH 6.12.y 1/6] cifs: Remove the server pointer from smb_message Sasha Levin
2026-09-07 15:00 ` [PATCH 6.12.y 2/6] cifs: Do some preparation prior to organising the function declarations Sasha Levin
2026-09-07 15:00 ` [PATCH 6.12.y 3/6] cifs: Remove dead function prototypes Sasha Levin
2026-09-07 15:00 ` [PATCH 6.12.y 4/6] cifs: Scripted clean up fs/smb/client/fscache.h Sasha Levin
2026-09-07 15:00 ` [PATCH 6.12.y 5/6] cifs: SMB1 split: Create smb1proto.h for SMB1 declarations Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox