Skip to content

Commit 83bfbd0

Browse files
dhowellssmfrench
authored andcommitted
cifs: Remove the RFC1002 header from smb_hdr
Remove the RFC1002 header from struct smb_hdr as used for SMB-1.0. This simplifies the SMB-1.0 code by simplifying a lot of places that have to add or subtract 4 to work around the fact that the RFC1002 header isn't really part of the message and the base for various offsets within the message is from the base of the smb_hdr, not the RFC1002 header. Further, clean up a bunch of places that require an extra kvec struct specifically pointing to the RFC1002 header, such that kvec[0].iov_base must be exactly 4 bytes before kvec[1].iov_base. This allows the header preamble size stuff to be removed too. The size of the request and response message are then handed around either directly or by summing the size of all the iov_len members in the kvec array for which we have a count. Also, this simplifies and cleans up the common transmission and receive paths for SMB1 and SMB2/3 as there no longer needs to be special handling casing for SMB1 messages as the RFC1002 header is now generated on the fly for SMB1 as it is for SMB2/3. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Tom Talpey <tom@talpey.com> Reviewed-by: Paulo Alcantara (Red Hat) <pc@manguebit.org> cc: Shyam Prasad N <sprasad@microsoft.com> 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>
1 parent 9d85ac9 commit 83bfbd0

19 files changed

Lines changed: 647 additions & 626 deletions

fs/smb/client/cifs_debug.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,15 @@ cifs_dump_mem(char *label, void *data, int length)
3737
data, length, true);
3838
}
3939

40-
void cifs_dump_detail(void *buf, struct TCP_Server_Info *server)
40+
void cifs_dump_detail(void *buf, size_t buf_len, struct TCP_Server_Info *server)
4141
{
4242
#ifdef CONFIG_CIFS_DEBUG2
4343
struct smb_hdr *smb = buf;
4444

4545
cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d Wct: %d\n",
4646
smb->Command, smb->Status.CifsError, smb->Flags,
4747
smb->Flags2, smb->Mid, smb->Pid, smb->WordCount);
48-
if (!server->ops->check_message(buf, server->total_read, server)) {
48+
if (!server->ops->check_message(buf, buf_len, server->total_read, server)) {
4949
cifs_dbg(VFS, "smb buf %p len %u\n", smb,
5050
server->ops->calc_smb_size(smb));
5151
}
@@ -79,9 +79,9 @@ void cifs_dump_mids(struct TCP_Server_Info *server)
7979
cifs_dbg(VFS, "IsMult: %d IsEnd: %d\n",
8080
mid_entry->multiRsp, mid_entry->multiEnd);
8181
if (mid_entry->resp_buf) {
82-
cifs_dump_detail(mid_entry->resp_buf, server);
83-
cifs_dump_mem("existing buf: ",
84-
mid_entry->resp_buf, 62);
82+
cifs_dump_detail(mid_entry->resp_buf,
83+
mid_entry->response_pdu_len, server);
84+
cifs_dump_mem("existing buf: ", mid_entry->resp_buf, 62);
8585
}
8686
}
8787
spin_unlock(&server->mid_queue_lock);

fs/smb/client/cifs_debug.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
#define pr_fmt(fmt) "CIFS: " fmt
1616

1717
void cifs_dump_mem(char *label, void *data, int length);
18-
void cifs_dump_detail(void *buf, struct TCP_Server_Info *ptcp_info);
19-
void cifs_dump_mids(struct TCP_Server_Info *);
18+
void cifs_dump_detail(void *buf, size_t buf_len, struct TCP_Server_Info *server);
19+
void cifs_dump_mids(struct TCP_Server_Info *server);
2020
extern bool traceSMB; /* flag which enables the function below */
21-
void dump_smb(void *, int);
21+
void dump_smb(void *buf, int smb_buf_length);
2222
#define CIFS_INFO 0x01
2323
#define CIFS_RC 0x02
2424
#define CIFS_TIMER 0x04

fs/smb/client/cifsencrypt.c

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -91,18 +91,7 @@ int __cifs_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
9191
struct kvec *iov = rqst->rq_iov;
9292
int n_vec = rqst->rq_nvec;
9393

94-
/* iov[0] is actual data and not the rfc1002 length for SMB2+ */
95-
if (!is_smb1(server)) {
96-
if (iov[0].iov_len <= 4)
97-
return -EIO;
98-
i = 0;
99-
} else {
100-
if (n_vec < 2 || iov[0].iov_len != 4)
101-
return -EIO;
102-
i = 1; /* skip rfc1002 length */
103-
}
104-
105-
for (; i < n_vec; i++) {
94+
for (i = 0; i < n_vec; i++) {
10695
if (iov[i].iov_len == 0)
10796
continue;
10897
if (iov[i].iov_base == NULL) {
@@ -165,10 +154,6 @@ int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
165154
char smb_signature[20];
166155
struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
167156

168-
if (rqst->rq_iov[0].iov_len != 4 ||
169-
rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
170-
return -EIO;
171-
172157
if ((cifs_pdu == NULL) || (server == NULL))
173158
return -EINVAL;
174159

@@ -211,17 +196,16 @@ int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
211196
}
212197

213198
/* must be called with server->srv_mutex held */
214-
int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
199+
int cifs_sign_smb(struct smb_hdr *cifs_pdu, unsigned int pdu_len,
200+
struct TCP_Server_Info *server,
215201
__u32 *pexpected_response_sequence_number)
216202
{
217-
struct kvec iov[2];
203+
struct kvec iov[1] = {
204+
[0].iov_base = (char *)cifs_pdu,
205+
[0].iov_len = pdu_len,
206+
};
218207

219-
iov[0].iov_base = cifs_pdu;
220-
iov[0].iov_len = 4;
221-
iov[1].iov_base = (char *)cifs_pdu + 4;
222-
iov[1].iov_len = be32_to_cpu(cifs_pdu->smb_buf_length);
223-
224-
return cifs_sign_smbv(iov, 2, server,
208+
return cifs_sign_smbv(iov, ARRAY_SIZE(iov), server,
225209
pexpected_response_sequence_number);
226210
}
227211

@@ -234,10 +218,6 @@ int cifs_verify_signature(struct smb_rqst *rqst,
234218
char what_we_think_sig_should_be[20];
235219
struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
236220

237-
if (rqst->rq_iov[0].iov_len != 4 ||
238-
rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
239-
return -EIO;
240-
241221
if (cifs_pdu == NULL || server == NULL)
242222
return -EINVAL;
243223

fs/smb/client/cifsglob.h

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -346,13 +346,14 @@ struct smb_version_operations {
346346
/* map smb to linux error */
347347
int (*map_error)(char *, bool);
348348
/* find mid corresponding to the response message */
349-
struct mid_q_entry * (*find_mid)(struct TCP_Server_Info *, char *);
350-
void (*dump_detail)(void *buf, struct TCP_Server_Info *ptcp_info);
349+
struct mid_q_entry *(*find_mid)(struct TCP_Server_Info *server, char *buf);
350+
void (*dump_detail)(void *buf, size_t buf_len, struct TCP_Server_Info *ptcp_info);
351351
void (*clear_stats)(struct cifs_tcon *);
352352
void (*print_stats)(struct seq_file *m, struct cifs_tcon *);
353353
void (*dump_share_caps)(struct seq_file *, struct cifs_tcon *);
354354
/* verify the message */
355-
int (*check_message)(char *, unsigned int, struct TCP_Server_Info *);
355+
int (*check_message)(char *buf, unsigned int pdu_len, unsigned int len,
356+
struct TCP_Server_Info *server);
356357
bool (*is_oplock_break)(char *, struct TCP_Server_Info *);
357358
int (*handle_cancelled_mid)(struct mid_q_entry *, struct TCP_Server_Info *);
358359
void (*downgrade_oplock)(struct TCP_Server_Info *server,
@@ -636,8 +637,7 @@ struct smb_version_operations {
636637

637638
#define HEADER_SIZE(server) (server->vals->header_size)
638639
#define MAX_HEADER_SIZE(server) (server->vals->max_header_size)
639-
#define HEADER_PREAMBLE_SIZE(server) (server->vals->header_preamble_size)
640-
#define MID_HEADER_SIZE(server) (HEADER_SIZE(server) - 1 - HEADER_PREAMBLE_SIZE(server))
640+
#define MID_HEADER_SIZE(server) (HEADER_SIZE(server) - 1)
641641

642642
/**
643643
* CIFS superblock mount flags (mnt_cifs_flags) to consider when
@@ -832,9 +832,9 @@ struct TCP_Server_Info {
832832
char dns_dom[CIFS_MAX_DOMAINNAME_LEN + 1];
833833
};
834834

835-
static inline bool is_smb1(struct TCP_Server_Info *server)
835+
static inline bool is_smb1(const struct TCP_Server_Info *server)
836836
{
837-
return HEADER_PREAMBLE_SIZE(server) != 0;
837+
return server->vals->protocol_id == SMB10_PROT_ID;
838838
}
839839

840840
static inline void cifs_server_lock(struct TCP_Server_Info *server)
@@ -973,16 +973,16 @@ compare_mid(__u16 mid, const struct smb_hdr *smb)
973973
* of kvecs to handle the receive, though that should only need to be done
974974
* once.
975975
*/
976-
#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
977-
#define CIFS_MAX_RSIZE ((1<<24) - sizeof(READ_RSP) + 4)
976+
#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ))
977+
#define CIFS_MAX_RSIZE ((1<<24) - sizeof(READ_RSP))
978978

979979
/*
980980
* When the server doesn't allow large posix writes, only allow a rsize/wsize
981981
* of 2^17-1 minus the size of the call header. That allows for a read or
982982
* write up to the maximum size described by RFC1002.
983983
*/
984-
#define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4)
985-
#define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP) + 4)
984+
#define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ))
985+
#define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP))
986986

987987
/*
988988
* Windows only supports a max of 60kb reads and 65535 byte writes. Default to
@@ -1701,6 +1701,7 @@ struct mid_q_entry {
17011701
struct task_struct *creator;
17021702
void *resp_buf; /* pointer to received SMB header */
17031703
unsigned int resp_buf_size;
1704+
u32 response_pdu_len;
17041705
int mid_state; /* wish this were enum but can not pass to wait_event */
17051706
int mid_rc; /* rc for MID_RC */
17061707
__le16 command; /* smb command code */

fs/smb/client/cifspdu.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090

9191
/* future chained NTCreateXReadX bigger, but for time being NTCreateX biggest */
9292
/* among the requests (NTCreateX response is bigger with wct of 34) */
93-
#define MAX_CIFS_HDR_SIZE 0x58 /* 4 len + 32 hdr + (2*24 wct) + 2 bct + 2 pad */
93+
#define MAX_CIFS_HDR_SIZE 0x54 /* 32 hdr + (2*24 wct) + 2 bct + 2 pad */
9494
#define CIFS_SMALL_PATH 120 /* allows for (448-88)/3 */
9595

9696
/* internal cifs vfs structures */

fs/smb/client/cifsproto.h

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -111,18 +111,16 @@ extern int compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
111111
const int flags, const int num_rqst,
112112
struct smb_rqst *rqst, int *resp_buf_type,
113113
struct kvec *resp_iov);
114-
extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *,
115-
struct smb_hdr * /* input */ ,
116-
struct smb_hdr * /* out */ ,
117-
int * /* bytes returned */ , const int);
118-
extern int SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
119-
char *in_buf, int flags);
114+
int SendReceive(const unsigned int xid, struct cifs_ses *ses,
115+
struct smb_hdr *in_buf, unsigned int in_len,
116+
struct smb_hdr *out_buf, int *pbytes_returned, const int flags);
117+
int SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
118+
char *in_buf, unsigned int in_len, int flags);
120119
int cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server);
121-
extern struct mid_q_entry *cifs_setup_request(struct cifs_ses *,
122-
struct TCP_Server_Info *,
123-
struct smb_rqst *);
124-
extern struct mid_q_entry *cifs_setup_async_request(struct TCP_Server_Info *,
125-
struct smb_rqst *);
120+
struct mid_q_entry *cifs_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *ignored,
121+
struct smb_rqst *rqst);
122+
struct mid_q_entry *cifs_setup_async_request(struct TCP_Server_Info *server,
123+
struct smb_rqst *rqst);
126124
int __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
127125
struct smb_rqst *rqst);
128126
extern int cifs_check_receive(struct mid_q_entry *mid,
@@ -146,11 +144,9 @@ extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *,
146144
struct kvec *, int /* nvec to send */,
147145
int * /* type of buf returned */, const int flags,
148146
struct kvec * /* resp vec */);
149-
extern int SendReceiveBlockingLock(const unsigned int xid,
150-
struct cifs_tcon *ptcon,
151-
struct smb_hdr *in_buf,
152-
struct smb_hdr *out_buf,
153-
int *bytes_returned);
147+
int SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
148+
struct smb_hdr *in_buf, unsigned int in_len,
149+
struct smb_hdr *out_buf, int *pbytes_returned);
154150

155151
void smb2_query_server_interfaces(struct work_struct *work);
156152
void
@@ -161,7 +157,8 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
161157
bool mark_smb_session);
162158
extern int cifs_reconnect(struct TCP_Server_Info *server,
163159
bool mark_smb_session);
164-
extern int checkSMB(char *buf, unsigned int len, struct TCP_Server_Info *srvr);
160+
int checkSMB(char *buf, unsigned int pdu_len, unsigned int len,
161+
struct TCP_Server_Info *srvr);
165162
extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *);
166163
extern bool backup_cred(struct cifs_sb_info *);
167164
extern bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 eof,
@@ -188,9 +185,9 @@ extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len);
188185
extern void cifs_set_port(struct sockaddr *addr, const unsigned short int port);
189186
extern int map_smb_to_linux_error(char *buf, bool logErr);
190187
extern int map_and_check_smb_error(struct mid_q_entry *mid, bool logErr);
191-
extern void header_assemble(struct smb_hdr *, char /* command */ ,
192-
const struct cifs_tcon *, int /* length of
193-
fixed section (word count) in two byte units */);
188+
unsigned int header_assemble(struct smb_hdr *buffer, char smb_command,
189+
const struct cifs_tcon *treeCon, int word_count
190+
/* length of fixed section word count in two byte units */);
194191
extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
195192
struct cifs_ses *ses,
196193
void **request_buf);
@@ -565,12 +562,14 @@ extern void tconInfoFree(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace)
565562

566563
extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
567564
__u32 *pexpected_response_sequence_number);
568-
extern int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
569-
__u32 *);
570-
extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
571-
extern int cifs_verify_signature(struct smb_rqst *rqst,
572-
struct TCP_Server_Info *server,
573-
__u32 expected_sequence_number);
565+
int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
566+
__u32 *pexpected_response_sequence);
567+
int cifs_sign_smb(struct smb_hdr *cifs_pdu, unsigned int pdu_len,
568+
struct TCP_Server_Info *server,
569+
__u32 *pexpected_response_sequence_number);
570+
int cifs_verify_signature(struct smb_rqst *rqst,
571+
struct TCP_Server_Info *server,
572+
__u32 expected_sequence_number);
574573
extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *);
575574
extern void cifs_crypto_secmech_release(struct TCP_Server_Info *server);
576575
extern int calc_seckey(struct cifs_ses *);

0 commit comments

Comments
 (0)